rasa-pro 3.12.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- README.md +41 -0
- rasa/__init__.py +9 -0
- rasa/__main__.py +177 -0
- rasa/anonymization/__init__.py +2 -0
- rasa/anonymization/anonymisation_rule_yaml_reader.py +91 -0
- rasa/anonymization/anonymization_pipeline.py +286 -0
- rasa/anonymization/anonymization_rule_executor.py +260 -0
- rasa/anonymization/anonymization_rule_orchestrator.py +120 -0
- rasa/anonymization/schemas/config.yml +47 -0
- rasa/anonymization/utils.py +118 -0
- rasa/api.py +160 -0
- rasa/cli/__init__.py +5 -0
- rasa/cli/arguments/__init__.py +0 -0
- rasa/cli/arguments/data.py +106 -0
- rasa/cli/arguments/default_arguments.py +207 -0
- rasa/cli/arguments/evaluate.py +65 -0
- rasa/cli/arguments/export.py +51 -0
- rasa/cli/arguments/interactive.py +74 -0
- rasa/cli/arguments/run.py +219 -0
- rasa/cli/arguments/shell.py +17 -0
- rasa/cli/arguments/test.py +211 -0
- rasa/cli/arguments/train.py +279 -0
- rasa/cli/arguments/visualize.py +34 -0
- rasa/cli/arguments/x.py +30 -0
- rasa/cli/data.py +354 -0
- rasa/cli/dialogue_understanding_test.py +251 -0
- rasa/cli/e2e_test.py +259 -0
- rasa/cli/evaluate.py +222 -0
- rasa/cli/export.py +250 -0
- rasa/cli/inspect.py +75 -0
- rasa/cli/interactive.py +166 -0
- rasa/cli/license.py +65 -0
- rasa/cli/llm_fine_tuning.py +403 -0
- rasa/cli/markers.py +78 -0
- rasa/cli/project_templates/__init__.py +0 -0
- rasa/cli/project_templates/calm/actions/__init__.py +0 -0
- rasa/cli/project_templates/calm/actions/action_template.py +27 -0
- rasa/cli/project_templates/calm/actions/add_contact.py +30 -0
- rasa/cli/project_templates/calm/actions/db.py +57 -0
- rasa/cli/project_templates/calm/actions/list_contacts.py +22 -0
- rasa/cli/project_templates/calm/actions/remove_contact.py +35 -0
- rasa/cli/project_templates/calm/config.yml +10 -0
- rasa/cli/project_templates/calm/credentials.yml +33 -0
- rasa/cli/project_templates/calm/data/flows/add_contact.yml +31 -0
- rasa/cli/project_templates/calm/data/flows/list_contacts.yml +14 -0
- rasa/cli/project_templates/calm/data/flows/remove_contact.yml +29 -0
- rasa/cli/project_templates/calm/db/contacts.json +10 -0
- rasa/cli/project_templates/calm/domain/add_contact.yml +39 -0
- rasa/cli/project_templates/calm/domain/list_contacts.yml +17 -0
- rasa/cli/project_templates/calm/domain/remove_contact.yml +38 -0
- rasa/cli/project_templates/calm/domain/shared.yml +10 -0
- rasa/cli/project_templates/calm/e2e_tests/cancelations/user_cancels_during_a_correction.yml +16 -0
- rasa/cli/project_templates/calm/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +7 -0
- rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_handle.yml +20 -0
- rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_name.yml +19 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +15 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_lists_contacts.yml +5 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact.yml +11 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact_from_list.yml +12 -0
- rasa/cli/project_templates/calm/endpoints.yml +58 -0
- rasa/cli/project_templates/default/actions/__init__.py +0 -0
- rasa/cli/project_templates/default/actions/actions.py +27 -0
- rasa/cli/project_templates/default/config.yml +44 -0
- rasa/cli/project_templates/default/credentials.yml +33 -0
- rasa/cli/project_templates/default/data/nlu.yml +91 -0
- rasa/cli/project_templates/default/data/rules.yml +13 -0
- rasa/cli/project_templates/default/data/stories.yml +30 -0
- rasa/cli/project_templates/default/domain.yml +34 -0
- rasa/cli/project_templates/default/endpoints.yml +42 -0
- rasa/cli/project_templates/default/tests/test_stories.yml +91 -0
- rasa/cli/project_templates/tutorial/actions/__init__.py +0 -0
- rasa/cli/project_templates/tutorial/actions/actions.py +22 -0
- rasa/cli/project_templates/tutorial/config.yml +12 -0
- rasa/cli/project_templates/tutorial/credentials.yml +33 -0
- rasa/cli/project_templates/tutorial/data/flows.yml +8 -0
- rasa/cli/project_templates/tutorial/data/patterns.yml +11 -0
- rasa/cli/project_templates/tutorial/domain.yml +35 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +55 -0
- rasa/cli/run.py +143 -0
- rasa/cli/scaffold.py +273 -0
- rasa/cli/shell.py +141 -0
- rasa/cli/studio/__init__.py +0 -0
- rasa/cli/studio/download.py +62 -0
- rasa/cli/studio/studio.py +296 -0
- rasa/cli/studio/train.py +59 -0
- rasa/cli/studio/upload.py +62 -0
- rasa/cli/telemetry.py +102 -0
- rasa/cli/test.py +280 -0
- rasa/cli/train.py +278 -0
- rasa/cli/utils.py +484 -0
- rasa/cli/visualize.py +40 -0
- rasa/cli/x.py +206 -0
- rasa/constants.py +45 -0
- rasa/core/__init__.py +17 -0
- rasa/core/actions/__init__.py +0 -0
- rasa/core/actions/action.py +1318 -0
- rasa/core/actions/action_clean_stack.py +59 -0
- rasa/core/actions/action_exceptions.py +24 -0
- rasa/core/actions/action_hangup.py +29 -0
- rasa/core/actions/action_repeat_bot_messages.py +89 -0
- rasa/core/actions/action_run_slot_rejections.py +210 -0
- rasa/core/actions/action_trigger_chitchat.py +31 -0
- rasa/core/actions/action_trigger_flow.py +109 -0
- rasa/core/actions/action_trigger_search.py +31 -0
- rasa/core/actions/constants.py +5 -0
- rasa/core/actions/custom_action_executor.py +191 -0
- rasa/core/actions/direct_custom_actions_executor.py +109 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +72 -0
- rasa/core/actions/forms.py +741 -0
- rasa/core/actions/grpc_custom_action_executor.py +251 -0
- rasa/core/actions/http_custom_action_executor.py +145 -0
- rasa/core/actions/loops.py +114 -0
- rasa/core/actions/two_stage_fallback.py +186 -0
- rasa/core/agent.py +559 -0
- rasa/core/auth_retry_tracker_store.py +122 -0
- rasa/core/brokers/__init__.py +0 -0
- rasa/core/brokers/broker.py +126 -0
- rasa/core/brokers/file.py +58 -0
- rasa/core/brokers/kafka.py +324 -0
- rasa/core/brokers/pika.py +388 -0
- rasa/core/brokers/sql.py +86 -0
- rasa/core/channels/__init__.py +61 -0
- rasa/core/channels/botframework.py +338 -0
- rasa/core/channels/callback.py +84 -0
- rasa/core/channels/channel.py +456 -0
- rasa/core/channels/console.py +241 -0
- rasa/core/channels/development_inspector.py +197 -0
- rasa/core/channels/facebook.py +419 -0
- rasa/core/channels/hangouts.py +329 -0
- rasa/core/channels/inspector/.eslintrc.cjs +25 -0
- rasa/core/channels/inspector/.gitignore +23 -0
- rasa/core/channels/inspector/README.md +54 -0
- rasa/core/channels/inspector/assets/favicon.ico +0 -0
- rasa/core/channels/inspector/assets/rasa-chat.js +2 -0
- rasa/core/channels/inspector/custom.d.ts +3 -0
- rasa/core/channels/inspector/dist/assets/arc-861ddd57.js +1 -0
- rasa/core/channels/inspector/dist/assets/array-9f3ba611.js +1 -0
- rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-921f02db.js +10 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-b436c4f8.js +2 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-511a23cb.js +2 -0
- rasa/core/channels/inspector/dist/assets/createText-62fc7601-ef476ecd.js +7 -0
- rasa/core/channels/inspector/dist/assets/edges-f2ad444c-f1878e0a.js +4 -0
- rasa/core/channels/inspector/dist/assets/erDiagram-9d236eb7-fac75185.js +51 -0
- rasa/core/channels/inspector/dist/assets/flowDb-1972c806-201c5bbc.js +6 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-f904ae41.js +4 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +1 -0
- rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-1813da66.js +139 -0
- rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-872af172.js +266 -0
- rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-34a0af5a.js +70 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-128cfa44.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-21dbcb97.woff +0 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-222b5e26.svg +329 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-9ad89b2a.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-42ba3e3d.js +1 -0
- rasa/core/channels/inspector/dist/assets/index-37817b51.js +1317 -0
- rasa/core/channels/inspector/dist/assets/index-3ee28881.css +1 -0
- rasa/core/channels/inspector/dist/assets/infoDiagram-736b4530-6b731386.js +7 -0
- rasa/core/channels/inspector/dist/assets/init-77b53fdd.js +1 -0
- rasa/core/channels/inspector/dist/assets/journeyDiagram-df861f2b-e8579ac6.js +139 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-60c05ee4.woff +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-8335d9b8.svg +438 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-9cc39c75.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-ead13ccf.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-16705655.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-5aeb07f9.woff +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9c459044.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9e2898a4.svg +435 -0
- rasa/core/channels/inspector/dist/assets/layout-89e6403a.js +1 -0
- rasa/core/channels/inspector/dist/assets/line-dc73d3fc.js +1 -0
- rasa/core/channels/inspector/dist/assets/linear-f5b1d2bc.js +1 -0
- rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-82cb74fa.js +109 -0
- rasa/core/channels/inspector/dist/assets/ordinal-ba9b4969.js +1 -0
- rasa/core/channels/inspector/dist/assets/path-53f90ab3.js +1 -0
- rasa/core/channels/inspector/dist/assets/pieDiagram-dbbf0591-bdf5f29b.js +35 -0
- rasa/core/channels/inspector/dist/assets/quadrantDiagram-4d7f4fd6-c7a0cbe4.js +7 -0
- rasa/core/channels/inspector/dist/assets/requirementDiagram-6fc4c22a-7ec5410f.js +52 -0
- rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-caee5554.js +8 -0
- rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-2935f8db.js +122 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-8f5d9693.js +1 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-d565d1de.js +1 -0
- rasa/core/channels/inspector/dist/assets/styles-080da4f6-75ad421d.js +110 -0
- rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-7e764226.js +159 -0
- rasa/core/channels/inspector/dist/assets/styles-9c745c82-7a4e0e61.js +207 -0
- rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-4019d1bf.js +1 -0
- rasa/core/channels/inspector/dist/assets/timeline-definition-5b62e21b-01ea12df.js +61 -0
- rasa/core/channels/inspector/dist/assets/xychartDiagram-2b33534f-89407137.js +7 -0
- rasa/core/channels/inspector/dist/index.html +42 -0
- rasa/core/channels/inspector/index.html +40 -0
- rasa/core/channels/inspector/jest.config.ts +13 -0
- rasa/core/channels/inspector/package.json +52 -0
- rasa/core/channels/inspector/setupTests.ts +2 -0
- rasa/core/channels/inspector/src/App.tsx +220 -0
- rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +108 -0
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +187 -0
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +136 -0
- rasa/core/channels/inspector/src/components/ExpandIcon.tsx +16 -0
- rasa/core/channels/inspector/src/components/FullscreenButton.tsx +45 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +22 -0
- rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +21 -0
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +32 -0
- rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +39 -0
- rasa/core/channels/inspector/src/components/Slots.tsx +91 -0
- rasa/core/channels/inspector/src/components/Welcome.tsx +54 -0
- rasa/core/channels/inspector/src/helpers/audiostream.ts +191 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +392 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +306 -0
- rasa/core/channels/inspector/src/helpers/utils.ts +127 -0
- rasa/core/channels/inspector/src/main.tsx +13 -0
- rasa/core/channels/inspector/src/theme/Button/Button.ts +29 -0
- rasa/core/channels/inspector/src/theme/Heading/Heading.ts +31 -0
- rasa/core/channels/inspector/src/theme/Input/Input.ts +27 -0
- rasa/core/channels/inspector/src/theme/Link/Link.ts +10 -0
- rasa/core/channels/inspector/src/theme/Modal/Modal.ts +47 -0
- rasa/core/channels/inspector/src/theme/Table/Table.tsx +38 -0
- rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +12 -0
- rasa/core/channels/inspector/src/theme/base/breakpoints.ts +8 -0
- rasa/core/channels/inspector/src/theme/base/colors.ts +88 -0
- rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +29 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.svg +329 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.svg +438 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.svg +435 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/radii.ts +9 -0
- rasa/core/channels/inspector/src/theme/base/shadows.ts +7 -0
- rasa/core/channels/inspector/src/theme/base/sizes.ts +7 -0
- rasa/core/channels/inspector/src/theme/base/space.ts +15 -0
- rasa/core/channels/inspector/src/theme/base/styles.ts +13 -0
- rasa/core/channels/inspector/src/theme/base/typography.ts +24 -0
- rasa/core/channels/inspector/src/theme/base/zIndices.ts +19 -0
- rasa/core/channels/inspector/src/theme/index.ts +101 -0
- rasa/core/channels/inspector/src/types.ts +84 -0
- rasa/core/channels/inspector/src/vite-env.d.ts +1 -0
- rasa/core/channels/inspector/tests/__mocks__/fileMock.ts +1 -0
- rasa/core/channels/inspector/tests/__mocks__/matchMedia.ts +16 -0
- rasa/core/channels/inspector/tests/__mocks__/styleMock.ts +1 -0
- rasa/core/channels/inspector/tests/renderWithProviders.tsx +14 -0
- rasa/core/channels/inspector/tsconfig.json +26 -0
- rasa/core/channels/inspector/tsconfig.node.json +10 -0
- rasa/core/channels/inspector/vite.config.ts +8 -0
- rasa/core/channels/inspector/yarn.lock +6249 -0
- rasa/core/channels/mattermost.py +229 -0
- rasa/core/channels/rasa_chat.py +126 -0
- rasa/core/channels/rest.py +230 -0
- rasa/core/channels/rocketchat.py +174 -0
- rasa/core/channels/slack.py +620 -0
- rasa/core/channels/socketio.py +302 -0
- rasa/core/channels/telegram.py +298 -0
- rasa/core/channels/twilio.py +169 -0
- rasa/core/channels/vier_cvg.py +374 -0
- rasa/core/channels/voice_ready/__init__.py +0 -0
- rasa/core/channels/voice_ready/audiocodes.py +501 -0
- rasa/core/channels/voice_ready/jambonz.py +121 -0
- rasa/core/channels/voice_ready/jambonz_protocol.py +396 -0
- rasa/core/channels/voice_ready/twilio_voice.py +403 -0
- rasa/core/channels/voice_ready/utils.py +37 -0
- rasa/core/channels/voice_stream/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
- rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
- rasa/core/channels/voice_stream/asr/azure.py +130 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
- rasa/core/channels/voice_stream/audio_bytes.py +8 -0
- rasa/core/channels/voice_stream/browser_audio.py +107 -0
- rasa/core/channels/voice_stream/call_state.py +23 -0
- rasa/core/channels/voice_stream/tts/__init__.py +0 -0
- rasa/core/channels/voice_stream/tts/azure.py +106 -0
- rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
- rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
- rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
- rasa/core/channels/voice_stream/util.py +57 -0
- rasa/core/channels/voice_stream/voice_channel.py +427 -0
- rasa/core/channels/webexteams.py +134 -0
- rasa/core/concurrent_lock_store.py +210 -0
- rasa/core/constants.py +112 -0
- rasa/core/evaluation/__init__.py +0 -0
- rasa/core/evaluation/marker.py +267 -0
- rasa/core/evaluation/marker_base.py +923 -0
- rasa/core/evaluation/marker_stats.py +293 -0
- rasa/core/evaluation/marker_tracker_loader.py +103 -0
- rasa/core/exceptions.py +29 -0
- rasa/core/exporter.py +284 -0
- rasa/core/featurizers/__init__.py +0 -0
- rasa/core/featurizers/precomputation.py +410 -0
- rasa/core/featurizers/single_state_featurizer.py +421 -0
- rasa/core/featurizers/tracker_featurizers.py +1262 -0
- rasa/core/http_interpreter.py +89 -0
- rasa/core/information_retrieval/__init__.py +7 -0
- rasa/core/information_retrieval/faiss.py +124 -0
- rasa/core/information_retrieval/information_retrieval.py +137 -0
- rasa/core/information_retrieval/milvus.py +59 -0
- rasa/core/information_retrieval/qdrant.py +96 -0
- rasa/core/jobs.py +63 -0
- rasa/core/lock.py +139 -0
- rasa/core/lock_store.py +343 -0
- rasa/core/migrate.py +403 -0
- rasa/core/nlg/__init__.py +3 -0
- rasa/core/nlg/callback.py +146 -0
- rasa/core/nlg/contextual_response_rephraser.py +320 -0
- rasa/core/nlg/generator.py +230 -0
- rasa/core/nlg/interpolator.py +143 -0
- rasa/core/nlg/response.py +155 -0
- rasa/core/nlg/summarize.py +70 -0
- rasa/core/persistor.py +538 -0
- rasa/core/policies/__init__.py +0 -0
- rasa/core/policies/ensemble.py +329 -0
- rasa/core/policies/enterprise_search_policy.py +905 -0
- rasa/core/policies/enterprise_search_prompt_template.jinja2 +25 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
- rasa/core/policies/flow_policy.py +205 -0
- rasa/core/policies/flows/__init__.py +0 -0
- rasa/core/policies/flows/flow_exceptions.py +44 -0
- rasa/core/policies/flows/flow_executor.py +754 -0
- rasa/core/policies/flows/flow_step_result.py +43 -0
- rasa/core/policies/intentless_policy.py +1031 -0
- rasa/core/policies/intentless_prompt_template.jinja2 +22 -0
- rasa/core/policies/memoization.py +538 -0
- rasa/core/policies/policy.py +725 -0
- rasa/core/policies/rule_policy.py +1273 -0
- rasa/core/policies/ted_policy.py +2169 -0
- rasa/core/policies/unexpected_intent_policy.py +1022 -0
- rasa/core/processor.py +1465 -0
- rasa/core/run.py +342 -0
- rasa/core/secrets_manager/__init__.py +0 -0
- rasa/core/secrets_manager/constants.py +36 -0
- rasa/core/secrets_manager/endpoints.py +391 -0
- rasa/core/secrets_manager/factory.py +241 -0
- rasa/core/secrets_manager/secret_manager.py +262 -0
- rasa/core/secrets_manager/vault.py +584 -0
- rasa/core/test.py +1335 -0
- rasa/core/tracker_store.py +1703 -0
- rasa/core/train.py +105 -0
- rasa/core/training/__init__.py +89 -0
- rasa/core/training/converters/__init__.py +0 -0
- rasa/core/training/converters/responses_prefix_converter.py +119 -0
- rasa/core/training/interactive.py +1744 -0
- rasa/core/training/story_conflict.py +381 -0
- rasa/core/training/training.py +93 -0
- rasa/core/utils.py +366 -0
- rasa/core/visualize.py +70 -0
- rasa/dialogue_understanding/__init__.py +0 -0
- rasa/dialogue_understanding/coexistence/__init__.py +0 -0
- rasa/dialogue_understanding/coexistence/constants.py +4 -0
- rasa/dialogue_understanding/coexistence/intent_based_router.py +196 -0
- rasa/dialogue_understanding/coexistence/llm_based_router.py +327 -0
- rasa/dialogue_understanding/coexistence/router_template.jinja2 +12 -0
- rasa/dialogue_understanding/commands/__init__.py +61 -0
- rasa/dialogue_understanding/commands/can_not_handle_command.py +70 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +125 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +44 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +57 -0
- rasa/dialogue_understanding/commands/clarify_command.py +86 -0
- rasa/dialogue_understanding/commands/command.py +85 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +297 -0
- rasa/dialogue_understanding/commands/error_command.py +79 -0
- rasa/dialogue_understanding/commands/free_form_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/handle_code_change_command.py +73 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +66 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +57 -0
- rasa/dialogue_understanding/commands/noop_command.py +54 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
- rasa/dialogue_understanding/commands/restart_command.py +58 -0
- rasa/dialogue_understanding/commands/session_end_command.py +61 -0
- rasa/dialogue_understanding/commands/session_start_command.py +59 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +160 -0
- rasa/dialogue_understanding/commands/skip_question_command.py +75 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +107 -0
- rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +45 -0
- rasa/dialogue_understanding/generator/__init__.py +21 -0
- rasa/dialogue_understanding/generator/command_generator.py +464 -0
- rasa/dialogue_understanding/generator/constants.py +27 -0
- rasa/dialogue_understanding/generator/flow_document_template.jinja2 +4 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +466 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +500 -0
- rasa/dialogue_understanding/generator/llm_command_generator.py +67 -0
- rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
- rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +920 -0
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +261 -0
- rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +60 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +486 -0
- rasa/dialogue_understanding/patterns/__init__.py +0 -0
- rasa/dialogue_understanding/patterns/cancel.py +111 -0
- rasa/dialogue_understanding/patterns/cannot_handle.py +43 -0
- rasa/dialogue_understanding/patterns/chitchat.py +37 -0
- rasa/dialogue_understanding/patterns/clarify.py +97 -0
- rasa/dialogue_understanding/patterns/code_change.py +41 -0
- rasa/dialogue_understanding/patterns/collect_information.py +90 -0
- rasa/dialogue_understanding/patterns/completed.py +40 -0
- rasa/dialogue_understanding/patterns/continue_interrupted.py +42 -0
- rasa/dialogue_understanding/patterns/correction.py +278 -0
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +301 -0
- rasa/dialogue_understanding/patterns/human_handoff.py +37 -0
- rasa/dialogue_understanding/patterns/internal_error.py +47 -0
- rasa/dialogue_understanding/patterns/repeat.py +37 -0
- rasa/dialogue_understanding/patterns/restart.py +37 -0
- rasa/dialogue_understanding/patterns/search.py +37 -0
- rasa/dialogue_understanding/patterns/session_start.py +37 -0
- rasa/dialogue_understanding/patterns/skip_question.py +38 -0
- rasa/dialogue_understanding/patterns/user_silence.py +37 -0
- rasa/dialogue_understanding/processor/__init__.py +0 -0
- rasa/dialogue_understanding/processor/command_processor.py +720 -0
- rasa/dialogue_understanding/processor/command_processor_component.py +43 -0
- rasa/dialogue_understanding/stack/__init__.py +0 -0
- rasa/dialogue_understanding/stack/dialogue_stack.py +178 -0
- rasa/dialogue_understanding/stack/frames/__init__.py +19 -0
- rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +27 -0
- rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +137 -0
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +157 -0
- rasa/dialogue_understanding/stack/frames/pattern_frame.py +10 -0
- rasa/dialogue_understanding/stack/frames/search_frame.py +27 -0
- rasa/dialogue_understanding/stack/utils.py +211 -0
- rasa/dialogue_understanding/utils.py +14 -0
- rasa/dialogue_understanding_test/__init__.py +0 -0
- rasa/dialogue_understanding_test/command_metric_calculation.py +12 -0
- rasa/dialogue_understanding_test/constants.py +17 -0
- rasa/dialogue_understanding_test/du_test_case.py +118 -0
- rasa/dialogue_understanding_test/du_test_result.py +11 -0
- rasa/dialogue_understanding_test/du_test_runner.py +93 -0
- rasa/dialogue_understanding_test/io.py +54 -0
- rasa/dialogue_understanding_test/validation.py +22 -0
- rasa/e2e_test/__init__.py +0 -0
- rasa/e2e_test/aggregate_test_stats_calculator.py +134 -0
- rasa/e2e_test/assertions.py +1345 -0
- rasa/e2e_test/assertions_schema.yml +129 -0
- rasa/e2e_test/constants.py +31 -0
- rasa/e2e_test/e2e_config.py +220 -0
- rasa/e2e_test/e2e_config_schema.yml +26 -0
- rasa/e2e_test/e2e_test_case.py +569 -0
- rasa/e2e_test/e2e_test_converter.py +363 -0
- rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
- rasa/e2e_test/e2e_test_coverage_report.py +364 -0
- rasa/e2e_test/e2e_test_result.py +54 -0
- rasa/e2e_test/e2e_test_runner.py +1192 -0
- rasa/e2e_test/e2e_test_schema.yml +181 -0
- rasa/e2e_test/pykwalify_extensions.py +39 -0
- rasa/e2e_test/stub_custom_action.py +70 -0
- rasa/e2e_test/utils/__init__.py +0 -0
- rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
- rasa/e2e_test/utils/io.py +598 -0
- rasa/e2e_test/utils/validation.py +178 -0
- rasa/engine/__init__.py +0 -0
- rasa/engine/caching.py +463 -0
- rasa/engine/constants.py +17 -0
- rasa/engine/exceptions.py +14 -0
- rasa/engine/graph.py +642 -0
- rasa/engine/loader.py +48 -0
- rasa/engine/recipes/__init__.py +0 -0
- rasa/engine/recipes/config_files/default_config.yml +41 -0
- rasa/engine/recipes/default_components.py +97 -0
- rasa/engine/recipes/default_recipe.py +1272 -0
- rasa/engine/recipes/graph_recipe.py +79 -0
- rasa/engine/recipes/recipe.py +93 -0
- rasa/engine/runner/__init__.py +0 -0
- rasa/engine/runner/dask.py +250 -0
- rasa/engine/runner/interface.py +49 -0
- rasa/engine/storage/__init__.py +0 -0
- rasa/engine/storage/local_model_storage.py +244 -0
- rasa/engine/storage/resource.py +110 -0
- rasa/engine/storage/storage.py +199 -0
- rasa/engine/training/__init__.py +0 -0
- rasa/engine/training/components.py +176 -0
- rasa/engine/training/fingerprinting.py +64 -0
- rasa/engine/training/graph_trainer.py +256 -0
- rasa/engine/training/hooks.py +164 -0
- rasa/engine/validation.py +1451 -0
- rasa/env.py +14 -0
- rasa/exceptions.py +69 -0
- rasa/graph_components/__init__.py +0 -0
- rasa/graph_components/converters/__init__.py +0 -0
- rasa/graph_components/converters/nlu_message_converter.py +48 -0
- rasa/graph_components/providers/__init__.py +0 -0
- rasa/graph_components/providers/domain_for_core_training_provider.py +87 -0
- rasa/graph_components/providers/domain_provider.py +71 -0
- rasa/graph_components/providers/flows_provider.py +74 -0
- rasa/graph_components/providers/forms_provider.py +44 -0
- rasa/graph_components/providers/nlu_training_data_provider.py +56 -0
- rasa/graph_components/providers/responses_provider.py +44 -0
- rasa/graph_components/providers/rule_only_provider.py +49 -0
- rasa/graph_components/providers/story_graph_provider.py +96 -0
- rasa/graph_components/providers/training_tracker_provider.py +55 -0
- rasa/graph_components/validators/__init__.py +0 -0
- rasa/graph_components/validators/default_recipe_validator.py +550 -0
- rasa/graph_components/validators/finetuning_validator.py +302 -0
- rasa/hooks.py +111 -0
- rasa/jupyter.py +63 -0
- rasa/llm_fine_tuning/__init__.py +0 -0
- rasa/llm_fine_tuning/annotation_module.py +241 -0
- rasa/llm_fine_tuning/conversations.py +144 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
- rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
- rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
- rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
- rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
- rasa/llm_fine_tuning/storage.py +174 -0
- rasa/llm_fine_tuning/train_test_split_module.py +441 -0
- rasa/markers/__init__.py +0 -0
- rasa/markers/marker.py +269 -0
- rasa/markers/marker_base.py +828 -0
- rasa/markers/upload.py +74 -0
- rasa/markers/validate.py +21 -0
- rasa/model.py +118 -0
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +40 -0
- rasa/model_manager/model_api.py +559 -0
- rasa/model_manager/runner_service.py +286 -0
- rasa/model_manager/socket_bridge.py +146 -0
- rasa/model_manager/studio_jwt_auth.py +86 -0
- rasa/model_manager/trainer_service.py +325 -0
- rasa/model_manager/utils.py +87 -0
- rasa/model_manager/warm_rasa_process.py +187 -0
- rasa/model_service.py +112 -0
- rasa/model_testing.py +457 -0
- rasa/model_training.py +596 -0
- rasa/nlu/__init__.py +7 -0
- rasa/nlu/classifiers/__init__.py +3 -0
- rasa/nlu/classifiers/classifier.py +5 -0
- rasa/nlu/classifiers/diet_classifier.py +1881 -0
- rasa/nlu/classifiers/fallback_classifier.py +192 -0
- rasa/nlu/classifiers/keyword_intent_classifier.py +188 -0
- rasa/nlu/classifiers/logistic_regression_classifier.py +253 -0
- rasa/nlu/classifiers/mitie_intent_classifier.py +156 -0
- rasa/nlu/classifiers/regex_message_handler.py +56 -0
- rasa/nlu/classifiers/sklearn_intent_classifier.py +330 -0
- rasa/nlu/constants.py +77 -0
- rasa/nlu/convert.py +40 -0
- rasa/nlu/emulators/__init__.py +0 -0
- rasa/nlu/emulators/dialogflow.py +55 -0
- rasa/nlu/emulators/emulator.py +49 -0
- rasa/nlu/emulators/luis.py +86 -0
- rasa/nlu/emulators/no_emulator.py +10 -0
- rasa/nlu/emulators/wit.py +56 -0
- rasa/nlu/extractors/__init__.py +0 -0
- rasa/nlu/extractors/crf_entity_extractor.py +715 -0
- rasa/nlu/extractors/duckling_entity_extractor.py +206 -0
- rasa/nlu/extractors/entity_synonyms.py +178 -0
- rasa/nlu/extractors/extractor.py +470 -0
- rasa/nlu/extractors/mitie_entity_extractor.py +293 -0
- rasa/nlu/extractors/regex_entity_extractor.py +220 -0
- rasa/nlu/extractors/spacy_entity_extractor.py +95 -0
- rasa/nlu/featurizers/__init__.py +0 -0
- rasa/nlu/featurizers/dense_featurizer/__init__.py +0 -0
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +445 -0
- rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +57 -0
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +768 -0
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +170 -0
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +132 -0
- rasa/nlu/featurizers/featurizer.py +89 -0
- rasa/nlu/featurizers/sparse_featurizer/__init__.py +0 -0
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +867 -0
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +571 -0
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +271 -0
- rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +9 -0
- rasa/nlu/model.py +24 -0
- rasa/nlu/run.py +27 -0
- rasa/nlu/selectors/__init__.py +0 -0
- rasa/nlu/selectors/response_selector.py +987 -0
- rasa/nlu/test.py +1940 -0
- rasa/nlu/tokenizers/__init__.py +0 -0
- rasa/nlu/tokenizers/jieba_tokenizer.py +148 -0
- rasa/nlu/tokenizers/mitie_tokenizer.py +75 -0
- rasa/nlu/tokenizers/spacy_tokenizer.py +72 -0
- rasa/nlu/tokenizers/tokenizer.py +239 -0
- rasa/nlu/tokenizers/whitespace_tokenizer.py +95 -0
- rasa/nlu/utils/__init__.py +35 -0
- rasa/nlu/utils/bilou_utils.py +462 -0
- rasa/nlu/utils/hugging_face/__init__.py +0 -0
- rasa/nlu/utils/hugging_face/registry.py +108 -0
- rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +311 -0
- rasa/nlu/utils/mitie_utils.py +113 -0
- rasa/nlu/utils/pattern_utils.py +168 -0
- rasa/nlu/utils/spacy_utils.py +310 -0
- rasa/plugin.py +90 -0
- rasa/server.py +1588 -0
- rasa/shared/__init__.py +0 -0
- rasa/shared/constants.py +311 -0
- rasa/shared/core/__init__.py +0 -0
- rasa/shared/core/command_payload_reader.py +109 -0
- rasa/shared/core/constants.py +180 -0
- rasa/shared/core/conversation.py +46 -0
- rasa/shared/core/domain.py +2172 -0
- rasa/shared/core/events.py +2559 -0
- rasa/shared/core/flows/__init__.py +7 -0
- rasa/shared/core/flows/flow.py +562 -0
- rasa/shared/core/flows/flow_path.py +84 -0
- rasa/shared/core/flows/flow_step.py +146 -0
- rasa/shared/core/flows/flow_step_links.py +319 -0
- rasa/shared/core/flows/flow_step_sequence.py +70 -0
- rasa/shared/core/flows/flows_list.py +258 -0
- rasa/shared/core/flows/flows_yaml_schema.json +303 -0
- rasa/shared/core/flows/nlu_trigger.py +117 -0
- rasa/shared/core/flows/steps/__init__.py +24 -0
- rasa/shared/core/flows/steps/action.py +56 -0
- rasa/shared/core/flows/steps/call.py +64 -0
- rasa/shared/core/flows/steps/collect.py +112 -0
- rasa/shared/core/flows/steps/constants.py +5 -0
- rasa/shared/core/flows/steps/continuation.py +36 -0
- rasa/shared/core/flows/steps/end.py +22 -0
- rasa/shared/core/flows/steps/internal.py +44 -0
- rasa/shared/core/flows/steps/link.py +51 -0
- rasa/shared/core/flows/steps/no_operation.py +48 -0
- rasa/shared/core/flows/steps/set_slots.py +50 -0
- rasa/shared/core/flows/steps/start.py +30 -0
- rasa/shared/core/flows/utils.py +39 -0
- rasa/shared/core/flows/validation.py +735 -0
- rasa/shared/core/flows/yaml_flows_io.py +405 -0
- rasa/shared/core/generator.py +908 -0
- rasa/shared/core/slot_mappings.py +526 -0
- rasa/shared/core/slots.py +654 -0
- rasa/shared/core/trackers.py +1183 -0
- rasa/shared/core/training_data/__init__.py +0 -0
- rasa/shared/core/training_data/loading.py +89 -0
- rasa/shared/core/training_data/story_reader/__init__.py +0 -0
- rasa/shared/core/training_data/story_reader/story_reader.py +129 -0
- rasa/shared/core/training_data/story_reader/story_step_builder.py +168 -0
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +888 -0
- rasa/shared/core/training_data/story_writer/__init__.py +0 -0
- rasa/shared/core/training_data/story_writer/story_writer.py +76 -0
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +444 -0
- rasa/shared/core/training_data/structures.py +858 -0
- rasa/shared/core/training_data/visualization.html +146 -0
- rasa/shared/core/training_data/visualization.py +603 -0
- rasa/shared/data.py +249 -0
- rasa/shared/engine/__init__.py +0 -0
- rasa/shared/engine/caching.py +26 -0
- rasa/shared/exceptions.py +167 -0
- rasa/shared/importers/__init__.py +0 -0
- rasa/shared/importers/importer.py +770 -0
- rasa/shared/importers/multi_project.py +215 -0
- rasa/shared/importers/rasa.py +108 -0
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/importers/utils.py +36 -0
- rasa/shared/nlu/__init__.py +0 -0
- rasa/shared/nlu/constants.py +53 -0
- rasa/shared/nlu/interpreter.py +10 -0
- rasa/shared/nlu/training_data/__init__.py +0 -0
- rasa/shared/nlu/training_data/entities_parser.py +208 -0
- rasa/shared/nlu/training_data/features.py +492 -0
- rasa/shared/nlu/training_data/formats/__init__.py +10 -0
- rasa/shared/nlu/training_data/formats/dialogflow.py +163 -0
- rasa/shared/nlu/training_data/formats/luis.py +87 -0
- rasa/shared/nlu/training_data/formats/rasa.py +135 -0
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +618 -0
- rasa/shared/nlu/training_data/formats/readerwriter.py +244 -0
- rasa/shared/nlu/training_data/formats/wit.py +52 -0
- rasa/shared/nlu/training_data/loading.py +137 -0
- rasa/shared/nlu/training_data/lookup_tables_parser.py +30 -0
- rasa/shared/nlu/training_data/message.py +490 -0
- rasa/shared/nlu/training_data/schemas/__init__.py +0 -0
- rasa/shared/nlu/training_data/schemas/data_schema.py +85 -0
- rasa/shared/nlu/training_data/schemas/nlu.yml +53 -0
- rasa/shared/nlu/training_data/schemas/responses.yml +70 -0
- rasa/shared/nlu/training_data/synonyms_parser.py +42 -0
- rasa/shared/nlu/training_data/training_data.py +729 -0
- rasa/shared/nlu/training_data/util.py +223 -0
- rasa/shared/providers/__init__.py +0 -0
- rasa/shared/providers/_configs/__init__.py +0 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +677 -0
- rasa/shared/providers/_configs/client_config.py +59 -0
- rasa/shared/providers/_configs/default_litellm_client_config.py +132 -0
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +236 -0
- rasa/shared/providers/_configs/litellm_router_client_config.py +222 -0
- rasa/shared/providers/_configs/model_group_config.py +173 -0
- rasa/shared/providers/_configs/openai_client_config.py +177 -0
- rasa/shared/providers/_configs/rasa_llm_client_config.py +75 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +178 -0
- rasa/shared/providers/_configs/utils.py +117 -0
- rasa/shared/providers/_ssl_verification_utils.py +124 -0
- rasa/shared/providers/_utils.py +79 -0
- rasa/shared/providers/constants.py +7 -0
- rasa/shared/providers/embedding/__init__.py +0 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +243 -0
- rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +335 -0
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +126 -0
- rasa/shared/providers/embedding/embedding_client.py +90 -0
- rasa/shared/providers/embedding/embedding_response.py +41 -0
- rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +138 -0
- rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
- rasa/shared/providers/llm/__init__.py +0 -0
- rasa/shared/providers/llm/_base_litellm_client.py +265 -0
- rasa/shared/providers/llm/azure_openai_llm_client.py +415 -0
- rasa/shared/providers/llm/default_litellm_llm_client.py +110 -0
- rasa/shared/providers/llm/litellm_router_llm_client.py +202 -0
- rasa/shared/providers/llm/llm_client.py +78 -0
- rasa/shared/providers/llm/llm_response.py +50 -0
- rasa/shared/providers/llm/openai_llm_client.py +161 -0
- rasa/shared/providers/llm/rasa_llm_client.py +120 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +276 -0
- rasa/shared/providers/mappings.py +94 -0
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +185 -0
- rasa/shared/providers/router/router_client.py +75 -0
- rasa/shared/utils/__init__.py +0 -0
- rasa/shared/utils/cli.py +102 -0
- rasa/shared/utils/common.py +324 -0
- rasa/shared/utils/constants.py +4 -0
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
- rasa/shared/utils/health_check/health_check.py +258 -0
- rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
- rasa/shared/utils/io.py +499 -0
- rasa/shared/utils/llm.py +764 -0
- rasa/shared/utils/pykwalify_extensions.py +27 -0
- rasa/shared/utils/schemas/__init__.py +0 -0
- rasa/shared/utils/schemas/config.yml +2 -0
- rasa/shared/utils/schemas/domain.yml +145 -0
- rasa/shared/utils/schemas/events.py +214 -0
- rasa/shared/utils/schemas/model_config.yml +36 -0
- rasa/shared/utils/schemas/stories.yml +173 -0
- rasa/shared/utils/yaml.py +1068 -0
- rasa/studio/__init__.py +0 -0
- rasa/studio/auth.py +270 -0
- rasa/studio/config.py +136 -0
- rasa/studio/constants.py +19 -0
- rasa/studio/data_handler.py +368 -0
- rasa/studio/download.py +489 -0
- rasa/studio/results_logger.py +137 -0
- rasa/studio/train.py +134 -0
- rasa/studio/upload.py +563 -0
- rasa/telemetry.py +1876 -0
- rasa/tracing/__init__.py +0 -0
- rasa/tracing/config.py +355 -0
- rasa/tracing/constants.py +62 -0
- rasa/tracing/instrumentation/__init__.py +0 -0
- rasa/tracing/instrumentation/attribute_extractors.py +765 -0
- rasa/tracing/instrumentation/instrumentation.py +1306 -0
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +144 -0
- rasa/tracing/instrumentation/metrics.py +294 -0
- rasa/tracing/metric_instrument_provider.py +205 -0
- rasa/utils/__init__.py +0 -0
- rasa/utils/beta.py +83 -0
- rasa/utils/cli.py +28 -0
- rasa/utils/common.py +639 -0
- rasa/utils/converter.py +53 -0
- rasa/utils/endpoints.py +331 -0
- rasa/utils/io.py +252 -0
- rasa/utils/json_utils.py +60 -0
- rasa/utils/licensing.py +542 -0
- rasa/utils/log_utils.py +181 -0
- rasa/utils/mapper.py +210 -0
- rasa/utils/ml_utils.py +147 -0
- rasa/utils/plotting.py +362 -0
- rasa/utils/sanic_error_handler.py +32 -0
- rasa/utils/singleton.py +23 -0
- rasa/utils/tensorflow/__init__.py +0 -0
- rasa/utils/tensorflow/callback.py +112 -0
- rasa/utils/tensorflow/constants.py +116 -0
- rasa/utils/tensorflow/crf.py +492 -0
- rasa/utils/tensorflow/data_generator.py +440 -0
- rasa/utils/tensorflow/environment.py +161 -0
- rasa/utils/tensorflow/exceptions.py +5 -0
- rasa/utils/tensorflow/feature_array.py +366 -0
- rasa/utils/tensorflow/layers.py +1565 -0
- rasa/utils/tensorflow/layers_utils.py +113 -0
- rasa/utils/tensorflow/metrics.py +281 -0
- rasa/utils/tensorflow/model_data.py +798 -0
- rasa/utils/tensorflow/model_data_utils.py +499 -0
- rasa/utils/tensorflow/models.py +935 -0
- rasa/utils/tensorflow/rasa_layers.py +1094 -0
- rasa/utils/tensorflow/transformer.py +640 -0
- rasa/utils/tensorflow/types.py +6 -0
- rasa/utils/train_utils.py +572 -0
- rasa/utils/url_tools.py +53 -0
- rasa/utils/yaml.py +54 -0
- rasa/validator.py +1644 -0
- rasa/version.py +3 -0
- rasa_pro-3.12.0.dev1.dist-info/METADATA +199 -0
- rasa_pro-3.12.0.dev1.dist-info/NOTICE +5 -0
- rasa_pro-3.12.0.dev1.dist-info/RECORD +790 -0
- rasa_pro-3.12.0.dev1.dist-info/WHEEL +4 -0
- rasa_pro-3.12.0.dev1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import os
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import (
|
|
5
|
+
Dict,
|
|
6
|
+
Iterator,
|
|
7
|
+
Optional,
|
|
8
|
+
Set,
|
|
9
|
+
Text,
|
|
10
|
+
List,
|
|
11
|
+
Tuple,
|
|
12
|
+
Type,
|
|
13
|
+
TypeVar,
|
|
14
|
+
TYPE_CHECKING,
|
|
15
|
+
Union,
|
|
16
|
+
Any,
|
|
17
|
+
AsyncIterator,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
|
|
23
|
+
import rasa.shared.core.constants
|
|
24
|
+
import rasa.shared.nlu.constants
|
|
25
|
+
import rasa.shared.utils.io
|
|
26
|
+
import rasa.shared.utils.common
|
|
27
|
+
from rasa.shared.data import is_likely_yaml_file
|
|
28
|
+
from rasa.shared.exceptions import InvalidConfigException, RasaException
|
|
29
|
+
from rasa.shared.core.events import ActionExecuted, UserUttered, Event
|
|
30
|
+
from rasa import telemetry
|
|
31
|
+
from rasa.shared.core.domain import Domain
|
|
32
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
33
|
+
from rasa.shared.utils.yaml import read_yaml_file
|
|
34
|
+
from rasa.utils.io import WriteRow
|
|
35
|
+
from rasa.shared.constants import DOCS_URL_MARKERS
|
|
36
|
+
|
|
37
|
+
import logging
|
|
38
|
+
import csv
|
|
39
|
+
import os.path
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
from rasa.core.evaluation.marker import OrMarker
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class MarkerRegistry:
|
|
48
|
+
"""Keeps track of tags that can be used to configure markers."""
|
|
49
|
+
|
|
50
|
+
all_tags: Set[Text] = set() # noqa: RUF012
|
|
51
|
+
condition_tag_to_marker_class: Dict[Text, Type[ConditionMarker]] = {} # noqa: RUF012
|
|
52
|
+
operator_tag_to_marker_class: Dict[Text, Type[OperatorMarker]] = {} # noqa: RUF012
|
|
53
|
+
marker_class_to_tag: Dict[Type[Marker], Text] = {} # noqa: RUF012
|
|
54
|
+
negated_tag_to_tag: Dict[Text, Text] = {} # noqa: RUF012
|
|
55
|
+
tag_to_negated_tag: Dict[Text, Text] = {} # noqa: RUF012
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def register_builtin_markers(cls) -> None:
|
|
59
|
+
"""Must import all modules containing markers."""
|
|
60
|
+
import rasa.core.evaluation.marker # noqa
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def configurable_marker(cls, marker_class: Type[Marker]) -> Type[Marker]:
|
|
64
|
+
"""Decorator used to register a marker that can be used in config files.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
marker_class: the marker class to be made available via config files
|
|
68
|
+
Returns:
|
|
69
|
+
the registered marker class
|
|
70
|
+
"""
|
|
71
|
+
if not issubclass(marker_class, Marker):
|
|
72
|
+
raise RuntimeError("Can only register marker classes as configurable.")
|
|
73
|
+
|
|
74
|
+
tag = marker_class.positive_tag()
|
|
75
|
+
negated_tag = marker_class.negated_tag()
|
|
76
|
+
cls._register_tags(tags={tag, negated_tag})
|
|
77
|
+
cls._register_tag_class(marker_class=marker_class, positive_tag=tag)
|
|
78
|
+
cls._register_negation(tag=tag, negated_tag=negated_tag)
|
|
79
|
+
return marker_class
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def _register_tags(cls, tags: Set[Optional[Text]]) -> None:
|
|
83
|
+
specified_tags = {tag for tag in tags if tag is not None}
|
|
84
|
+
for tag_ in specified_tags:
|
|
85
|
+
if tag_ in cls.all_tags:
|
|
86
|
+
raise RuntimeError(
|
|
87
|
+
"Expected the tags of all configurable markers to be "
|
|
88
|
+
"identifiable by their tag."
|
|
89
|
+
)
|
|
90
|
+
cls.all_tags.add(tag_)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def _register_negation(cls, tag: Text, negated_tag: Optional[Text]) -> None:
|
|
94
|
+
if negated_tag is not None:
|
|
95
|
+
cls.negated_tag_to_tag[negated_tag] = tag
|
|
96
|
+
cls.tag_to_negated_tag[tag] = negated_tag
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def get_non_negated_tag(cls, tag_or_negated_tag: Text) -> Tuple[Text, bool]:
|
|
100
|
+
"""Returns the non-negated marker tag, given a (possible) negated marker tag.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
tag_or_negated_tag: the tag for a possibly negated marker
|
|
104
|
+
Returns:
|
|
105
|
+
the tag itself if it was already positive, otherwise the positive version;
|
|
106
|
+
and a boolean that represents whether the given tag was a negative one
|
|
107
|
+
"""
|
|
108
|
+
# either the given `marker_name` is already "positive" (e.g. "slot was set")
|
|
109
|
+
# or there is an entry mapping it to it's positive version:
|
|
110
|
+
positive_version = cls.negated_tag_to_tag.get(
|
|
111
|
+
tag_or_negated_tag, tag_or_negated_tag
|
|
112
|
+
)
|
|
113
|
+
is_negation = tag_or_negated_tag != positive_version
|
|
114
|
+
return positive_version, is_negation
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def _register_tag_class(
|
|
118
|
+
cls, marker_class: Type[Marker], positive_tag: Text
|
|
119
|
+
) -> None:
|
|
120
|
+
if issubclass(marker_class, ConditionMarker):
|
|
121
|
+
cls.condition_tag_to_marker_class[positive_tag] = marker_class
|
|
122
|
+
elif issubclass(marker_class, OperatorMarker):
|
|
123
|
+
cls.operator_tag_to_marker_class[positive_tag] = marker_class
|
|
124
|
+
else:
|
|
125
|
+
raise RuntimeError(
|
|
126
|
+
f"Can only register `{OperatorMarker.__name__} or "
|
|
127
|
+
f" {ConditionMarker.__name__} subclasses."
|
|
128
|
+
)
|
|
129
|
+
cls.marker_class_to_tag[marker_class] = positive_tag
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class InvalidMarkerConfig(RasaException):
|
|
133
|
+
"""Exception that can be raised when the config for a marker is not valid."""
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass
|
|
137
|
+
class EventMetaData:
|
|
138
|
+
"""Describes meta data per event in some session."""
|
|
139
|
+
|
|
140
|
+
idx: int
|
|
141
|
+
preceding_user_turns: int
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# We evaluate markers separately against every session and extract, for every marker
|
|
145
|
+
# that we want to evaluate, the meta data of the respective relevant events where the
|
|
146
|
+
# marker applies.
|
|
147
|
+
SessionEvaluation = Dict[Text, List[EventMetaData]]
|
|
148
|
+
|
|
149
|
+
T = TypeVar("T")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class Marker(ABC):
|
|
153
|
+
"""A marker is a way of describing points in conversations you're interested in.
|
|
154
|
+
|
|
155
|
+
Here, markers are stateful objects because they track the events of a conversation.
|
|
156
|
+
At each point in the conversation, one can observe whether a marker applies or
|
|
157
|
+
does not apply to the conversation so far.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
# Identifier for an artificial marker that is created when loading markers
|
|
161
|
+
# from a dictionary of configs. For more details, see `from_config_dict`.
|
|
162
|
+
ANY_MARKER = "<any_marker>"
|
|
163
|
+
|
|
164
|
+
def __init__(
|
|
165
|
+
self,
|
|
166
|
+
name: Optional[Text] = None,
|
|
167
|
+
negated: bool = False,
|
|
168
|
+
description: Optional[Text] = None,
|
|
169
|
+
) -> None:
|
|
170
|
+
"""Instantiates a marker.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
name: a custom name that can be used to replace the default string
|
|
174
|
+
conversion of this marker
|
|
175
|
+
negated: whether this marker should be negated (i.e. a negated marker
|
|
176
|
+
applies if and only if the non-negated marker does not apply)
|
|
177
|
+
description: an optional description of the marker. It is not used
|
|
178
|
+
internally but can be used to document the marker.
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
`InvalidMarkerConfig` if the chosen *name* of the marker is the tag of
|
|
182
|
+
a predefined marker.
|
|
183
|
+
"""
|
|
184
|
+
if name == Marker.ANY_MARKER or name in MarkerRegistry.all_tags:
|
|
185
|
+
raise InvalidMarkerConfig(
|
|
186
|
+
f"You must not use the special marker name {Marker.ANY_MARKER}. "
|
|
187
|
+
f"This is to avoid confusion when you generate a marker from a "
|
|
188
|
+
f"dictionary of marker configurations, which will lead to all "
|
|
189
|
+
f"markers being combined under one common `ORMarker` named "
|
|
190
|
+
f"{Marker.ANY_MARKER}."
|
|
191
|
+
)
|
|
192
|
+
self.name = name
|
|
193
|
+
self.history: List[bool] = []
|
|
194
|
+
# Note: we allow negation here even though there might not be a negated tag
|
|
195
|
+
# for 2 reasons: testing and the fact that the `MarkerRegistry`+`from_config`
|
|
196
|
+
# won't allow to create a negated marker if there is no negated tag.
|
|
197
|
+
self.negated: bool = negated
|
|
198
|
+
self.description = description
|
|
199
|
+
|
|
200
|
+
def __str__(self) -> Text:
|
|
201
|
+
return self.name or repr(self)
|
|
202
|
+
|
|
203
|
+
def __repr__(self) -> Text:
|
|
204
|
+
return self._to_str_with(self.get_tag())
|
|
205
|
+
|
|
206
|
+
def get_tag(self) -> Text:
|
|
207
|
+
"""Returns the tag describing this marker."""
|
|
208
|
+
if self.negated:
|
|
209
|
+
tag = self.negated_tag()
|
|
210
|
+
if tag is None:
|
|
211
|
+
# We allow the instantiation of a negated marker even if there
|
|
212
|
+
# is no negated tag (ie. direct creation of the negated marker from
|
|
213
|
+
# a config is not allowed). To be able to print a tag nonetheless:
|
|
214
|
+
tag = f"not({self.positive_tag()})"
|
|
215
|
+
return tag
|
|
216
|
+
else:
|
|
217
|
+
return self.positive_tag()
|
|
218
|
+
|
|
219
|
+
@staticmethod
|
|
220
|
+
@abstractmethod
|
|
221
|
+
def positive_tag() -> Text:
|
|
222
|
+
"""Returns the tag to be used in a config file."""
|
|
223
|
+
...
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def negated_tag() -> Optional[Text]:
|
|
227
|
+
"""Returns the tag to be used in a config file for the negated version.
|
|
228
|
+
|
|
229
|
+
If this maps to `None`, then this indicates that we do not allow a short-cut
|
|
230
|
+
for negating this marker. Hence, there is not a single tag to instantiate
|
|
231
|
+
a negated version of this marker. One must use a "not" in the configuration
|
|
232
|
+
file then.
|
|
233
|
+
"""
|
|
234
|
+
return None
|
|
235
|
+
|
|
236
|
+
@abstractmethod
|
|
237
|
+
def _to_str_with(self, tag: Text) -> Text:
|
|
238
|
+
"""Returns a string representation using the given tag."""
|
|
239
|
+
...
|
|
240
|
+
|
|
241
|
+
def track(self, event: Event) -> None:
|
|
242
|
+
"""Updates the marker according to the given event.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
event: the next event of the conversation
|
|
246
|
+
"""
|
|
247
|
+
result = self._non_negated_version_applies_at(event)
|
|
248
|
+
if self.negated:
|
|
249
|
+
result = not result
|
|
250
|
+
self.history.append(result)
|
|
251
|
+
|
|
252
|
+
@abstractmethod
|
|
253
|
+
def _non_negated_version_applies_at(self, event: Event) -> bool:
|
|
254
|
+
"""Checks whether the non-negated version applies at the next given event.
|
|
255
|
+
|
|
256
|
+
This method must *not* update the marker.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
event: the next event of the conversation
|
|
260
|
+
"""
|
|
261
|
+
...
|
|
262
|
+
|
|
263
|
+
def reset(self) -> None:
|
|
264
|
+
"""Clears the history of the marker."""
|
|
265
|
+
self.history = []
|
|
266
|
+
|
|
267
|
+
@abstractmethod
|
|
268
|
+
def flatten(self) -> Iterator[Marker]:
|
|
269
|
+
"""Returns an iterator over all conditions and operators used in this marker.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
an iterator over all conditions and operators that are part of this marker
|
|
273
|
+
"""
|
|
274
|
+
...
|
|
275
|
+
|
|
276
|
+
@abstractmethod
|
|
277
|
+
def validate_against_domain(self, domain: Domain) -> bool:
|
|
278
|
+
"""Checks that this marker (and its children) refer to entries in the domain.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
domain: The domain to check against
|
|
282
|
+
"""
|
|
283
|
+
...
|
|
284
|
+
|
|
285
|
+
@abstractmethod
|
|
286
|
+
def max_depth(self) -> int:
|
|
287
|
+
"""Gets the maximum depth from this point in the marker tree."""
|
|
288
|
+
...
|
|
289
|
+
|
|
290
|
+
def evaluate_events(self, events: List[Event]) -> List[SessionEvaluation]:
|
|
291
|
+
"""Resets the marker, tracks all events, and collects some information.
|
|
292
|
+
|
|
293
|
+
The collected information includes:
|
|
294
|
+
- the timestamp of each event where the marker applied and
|
|
295
|
+
- the number of user turns that preceded that timestamp
|
|
296
|
+
|
|
297
|
+
If this marker is the special `ANY_MARKER` (identified by its name), then
|
|
298
|
+
results will be collected for all (immediate) sub-markers.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
events: a list of events describing a conversation
|
|
302
|
+
Returns:
|
|
303
|
+
a list that contains, for each session contained in the tracker, a
|
|
304
|
+
dictionary mapping that maps marker names to meta data of relevant
|
|
305
|
+
events
|
|
306
|
+
"""
|
|
307
|
+
# determine which marker to extract results from
|
|
308
|
+
if isinstance(self, OperatorMarker) and self.name == Marker.ANY_MARKER:
|
|
309
|
+
markers_to_be_evaluated = self.sub_markers
|
|
310
|
+
else:
|
|
311
|
+
markers_to_be_evaluated = [self]
|
|
312
|
+
|
|
313
|
+
# split the events into sessions and evaluate them separately
|
|
314
|
+
sessions_and_start_indices = self._split_sessions(events=events)
|
|
315
|
+
|
|
316
|
+
extracted_markers: List[Dict[Text, List[EventMetaData]]] = []
|
|
317
|
+
for session, start_idx in sessions_and_start_indices:
|
|
318
|
+
# track all events and collect meta data per time step
|
|
319
|
+
meta_data = self._track_all_and_collect_meta_data(
|
|
320
|
+
events=session, event_idx_offset=start_idx
|
|
321
|
+
)
|
|
322
|
+
# for each marker, keep only certain meta data
|
|
323
|
+
extracted: Dict[Text, List[EventMetaData]] = {
|
|
324
|
+
str(marker): [meta_data[idx] for idx in marker.relevant_events()]
|
|
325
|
+
for marker in markers_to_be_evaluated
|
|
326
|
+
}
|
|
327
|
+
extracted_markers.append(extracted)
|
|
328
|
+
return extracted_markers
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def _split_sessions(events: List[Event]) -> List[Tuple[List[Event], int]]:
|
|
332
|
+
"""Identifies single sessions in a the given sequence of events.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
events: a sequence of events, e.g. extracted from a tracker store
|
|
336
|
+
Returns:
|
|
337
|
+
a list of sub-sequences of the given events that describe single
|
|
338
|
+
conversations and the respective index that describes where the
|
|
339
|
+
subsequence starts in the original sequence
|
|
340
|
+
"""
|
|
341
|
+
session_start_indices = [
|
|
342
|
+
idx
|
|
343
|
+
for idx, event in enumerate(events)
|
|
344
|
+
if isinstance(event, ActionExecuted)
|
|
345
|
+
and event.action_name
|
|
346
|
+
== rasa.shared.core.constants.ACTION_SESSION_START_NAME
|
|
347
|
+
]
|
|
348
|
+
if len(session_start_indices) == 0:
|
|
349
|
+
return [(events, 0)]
|
|
350
|
+
sessions_and_start_indices: List[Tuple[List[Event], int]] = []
|
|
351
|
+
for session_idx in range(len(session_start_indices) - 1):
|
|
352
|
+
start_idx = session_start_indices[session_idx]
|
|
353
|
+
end_idx = session_start_indices[session_idx + 1]
|
|
354
|
+
session = [events[idx] for idx in range(start_idx, end_idx)]
|
|
355
|
+
sessions_and_start_indices.append((session, start_idx))
|
|
356
|
+
last_session = [
|
|
357
|
+
events[idx] for idx in range(session_start_indices[-1], len(events))
|
|
358
|
+
]
|
|
359
|
+
sessions_and_start_indices.append((last_session, session_start_indices[-1]))
|
|
360
|
+
return sessions_and_start_indices
|
|
361
|
+
|
|
362
|
+
def _track_all_and_collect_meta_data(
|
|
363
|
+
self, events: List[Event], event_idx_offset: int = 0
|
|
364
|
+
) -> List[EventMetaData]:
|
|
365
|
+
"""Resets the marker, tracks all events, and collects metadata.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
events: all events of a *single* session that should be tracked and
|
|
369
|
+
evaluated
|
|
370
|
+
event_idx_offset: offset that will be used to modify the collected event
|
|
371
|
+
meta data, i.e. all event indices will be shifted by this offset
|
|
372
|
+
Returns:
|
|
373
|
+
metadata for each tracked event with all event indices shifted by the
|
|
374
|
+
given `event_idx_offset`
|
|
375
|
+
"""
|
|
376
|
+
self.reset()
|
|
377
|
+
session_meta_data: List[EventMetaData] = []
|
|
378
|
+
num_preceding_user_turns = 0
|
|
379
|
+
for idx, event in enumerate(events):
|
|
380
|
+
is_user_turn = isinstance(event, UserUttered)
|
|
381
|
+
session_meta_data.append(
|
|
382
|
+
EventMetaData(
|
|
383
|
+
idx=idx + event_idx_offset,
|
|
384
|
+
preceding_user_turns=num_preceding_user_turns,
|
|
385
|
+
)
|
|
386
|
+
)
|
|
387
|
+
self.track(event=event)
|
|
388
|
+
num_preceding_user_turns += int(is_user_turn)
|
|
389
|
+
return session_meta_data
|
|
390
|
+
|
|
391
|
+
def relevant_events(self) -> List[int]:
|
|
392
|
+
"""Returns the indices of those tracked events that are relevant for evaluation.
|
|
393
|
+
|
|
394
|
+
Note: Overwrite this method if you create a new marker class that should *not*
|
|
395
|
+
contain meta data about each event where the marker applied in the final
|
|
396
|
+
evaluation (see `evaluate_events`).
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
indices of tracked events
|
|
400
|
+
"""
|
|
401
|
+
return [idx for (idx, applies) in enumerate(self.history) if applies]
|
|
402
|
+
|
|
403
|
+
@classmethod
|
|
404
|
+
def from_path(cls, path: Union[Path, Text]) -> "OrMarker":
|
|
405
|
+
"""Loads markers from one config file or all config files in a directory tree.
|
|
406
|
+
|
|
407
|
+
Each config file should contain a dictionary mapping marker names to the
|
|
408
|
+
respective marker configuration.
|
|
409
|
+
To avoid confusion, the marker names must not coincide with the tag of
|
|
410
|
+
any pre-defined markers. Moreover, marker names must be unique. This means,
|
|
411
|
+
if you you load the markers from multiple files, then you have to make sure
|
|
412
|
+
that the names of the markers defined in these files are unique across all
|
|
413
|
+
loaded files.
|
|
414
|
+
|
|
415
|
+
Note that all loaded markers will be combined into one marker via one
|
|
416
|
+
artificial OR-operator. When evaluating the resulting marker, then the
|
|
417
|
+
artificial OR-operator will be ignored and results will be reported for
|
|
418
|
+
every sub-marker.
|
|
419
|
+
|
|
420
|
+
For more details how a single marker configuration looks like, have a look
|
|
421
|
+
at `Marker.from_config`.
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
path: either the path to a single config file or the root of the directory
|
|
425
|
+
tree that contains marker config files
|
|
426
|
+
Returns:
|
|
427
|
+
all configured markers, combined into one marker object
|
|
428
|
+
"""
|
|
429
|
+
MarkerRegistry.register_builtin_markers()
|
|
430
|
+
from rasa.core.evaluation.marker import OrMarker
|
|
431
|
+
|
|
432
|
+
# collect all the files from which we want to load configs (i.e. either just
|
|
433
|
+
# the given path if points to a yaml or all yaml-files in the directory tree)
|
|
434
|
+
yaml_files = cls._collect_yaml_files_from_path(path)
|
|
435
|
+
|
|
436
|
+
# collect all the configs from those yaml files (assure it's dictionaries
|
|
437
|
+
# mapping marker names to something) -- keep track of which config came
|
|
438
|
+
# from which file to be able to raise meaningful errors later
|
|
439
|
+
loaded_configs: Dict[Text, Dict] = cls._collect_configs_from_yaml_files(
|
|
440
|
+
yaml_files
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
# create markers from all loaded configurations
|
|
444
|
+
loaded_markers: List[Marker] = []
|
|
445
|
+
for yaml_file, config in loaded_configs.items():
|
|
446
|
+
for marker_name, marker_config in config.items():
|
|
447
|
+
try:
|
|
448
|
+
marker = Marker.from_config(marker_config, name=marker_name)
|
|
449
|
+
except InvalidMarkerConfig as e:
|
|
450
|
+
# we don't re-raise here because the stack trace would only be
|
|
451
|
+
# printed when we run rasa evaluate with --debug flag
|
|
452
|
+
raise InvalidMarkerConfig(
|
|
453
|
+
f"Could not load marker {marker_name} from {yaml_file}. "
|
|
454
|
+
f"Reason: {e!s}. "
|
|
455
|
+
)
|
|
456
|
+
loaded_markers.append(marker)
|
|
457
|
+
|
|
458
|
+
# Reminder: We could also just create a dictionary of markers from this.
|
|
459
|
+
# However, if we want to allow re-using top-level markers (e.g.
|
|
460
|
+
# "custom_marker1 or custom_marker2" and/or optimize the marker evaluation such
|
|
461
|
+
# that e.g. the same condition is not instantiated (and evaluated) twice, then
|
|
462
|
+
# the current approach might be better (e.g. with a dictionary of markers one
|
|
463
|
+
# might expect the markers to be independent objects).
|
|
464
|
+
|
|
465
|
+
# combine the markers
|
|
466
|
+
marker = OrMarker(markers=loaded_markers)
|
|
467
|
+
marker.name = Marker.ANY_MARKER # cannot be set via name parameter
|
|
468
|
+
return marker
|
|
469
|
+
|
|
470
|
+
@staticmethod
|
|
471
|
+
def _collect_yaml_files_from_path(path: Union[Text, Path]) -> List[Text]:
|
|
472
|
+
path = os.path.abspath(path)
|
|
473
|
+
if os.path.isfile(path):
|
|
474
|
+
yaml_files = [
|
|
475
|
+
yaml_file for yaml_file in [path] if is_likely_yaml_file(yaml_file)
|
|
476
|
+
]
|
|
477
|
+
if not yaml_files:
|
|
478
|
+
raise InvalidMarkerConfig(f"Could not find a yaml file at '{path}'.")
|
|
479
|
+
elif os.path.isdir(path):
|
|
480
|
+
yaml_files = [
|
|
481
|
+
os.path.join(root, file)
|
|
482
|
+
for root, _, files in os.walk(path, followlinks=True)
|
|
483
|
+
for file in files
|
|
484
|
+
if is_likely_yaml_file(file)
|
|
485
|
+
]
|
|
486
|
+
if not yaml_files:
|
|
487
|
+
raise InvalidMarkerConfig(
|
|
488
|
+
f"Could not find any yaml in the directory tree rooted at '{path}'."
|
|
489
|
+
)
|
|
490
|
+
else:
|
|
491
|
+
raise InvalidMarkerConfig(
|
|
492
|
+
f"The given path ({path}) is neither pointing to a directory "
|
|
493
|
+
f"nor a file. Please specify the location of a yaml file or a "
|
|
494
|
+
f"root directory (all yaml configs found in the directories "
|
|
495
|
+
f"under that root directory will be loaded). "
|
|
496
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
497
|
+
)
|
|
498
|
+
return yaml_files
|
|
499
|
+
|
|
500
|
+
@staticmethod
|
|
501
|
+
def _collect_configs_from_yaml_files(yaml_files: List[Text]) -> Dict[Text, Dict]:
|
|
502
|
+
marker_names: Set[Text] = set()
|
|
503
|
+
loaded_configs: Dict[Text, Dict] = {}
|
|
504
|
+
for yaml_file in yaml_files:
|
|
505
|
+
loaded_config = read_yaml_file(yaml_file)
|
|
506
|
+
if not isinstance(loaded_config, dict):
|
|
507
|
+
raise InvalidMarkerConfig(
|
|
508
|
+
f"Expected the loaded configurations to be a dictionary "
|
|
509
|
+
f"of marker configurations but found a "
|
|
510
|
+
f"{type(loaded_config)} in {yaml_file}. "
|
|
511
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
512
|
+
)
|
|
513
|
+
if set(loaded_config.keys()).intersection(marker_names):
|
|
514
|
+
raise InvalidMarkerConfig(
|
|
515
|
+
f"The names of markers defined in {yaml_file} "
|
|
516
|
+
f"({sorted(loaded_config.keys())}) "
|
|
517
|
+
f"overlap with the names of markers loaded so far "
|
|
518
|
+
f"({sorted(marker_names)}). "
|
|
519
|
+
f"Please adapt your configurations such that your custom "
|
|
520
|
+
f"marker names are unique. "
|
|
521
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
522
|
+
)
|
|
523
|
+
if set(loaded_config.keys()).intersection(MarkerRegistry.all_tags):
|
|
524
|
+
raise InvalidMarkerConfig(
|
|
525
|
+
f"The top level of your marker configuration should consist "
|
|
526
|
+
f"of names for your custom markers. "
|
|
527
|
+
f"If you use a condition or operator name at the top level, "
|
|
528
|
+
f"then that will not be recognised as an actual condition "
|
|
529
|
+
f"or operator and won't be evaluated against any sessions. "
|
|
530
|
+
f"Please remove any of the pre-defined marker tags "
|
|
531
|
+
f"(i.e. {MarkerRegistry.all_tags}) "
|
|
532
|
+
f"from {yaml_file}. "
|
|
533
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
534
|
+
)
|
|
535
|
+
marker_names.update(loaded_config.keys())
|
|
536
|
+
loaded_configs[yaml_file] = loaded_config
|
|
537
|
+
return loaded_configs
|
|
538
|
+
|
|
539
|
+
@staticmethod
|
|
540
|
+
def from_config(config: Any, name: Optional[Text] = None) -> Marker:
|
|
541
|
+
"""Creates a marker from the given config.
|
|
542
|
+
|
|
543
|
+
A marker configuration is a dictionary mapping a marker tag (either a
|
|
544
|
+
`positive_tag` or a `negated_tag`) to a sub-configuration.
|
|
545
|
+
How that sub-configuration looks like, depends on whether the tag describes
|
|
546
|
+
an operator (see `OperatorMarker.from_tag_and_sub_config`) or a
|
|
547
|
+
condition (see `ConditionMarker.from_tag_and_sub_config`).
|
|
548
|
+
|
|
549
|
+
Args:
|
|
550
|
+
config: a marker configuration
|
|
551
|
+
name: a custom name that will be used for the top-level marker (if and
|
|
552
|
+
only if there is only one top-level marker)
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
the configured marker
|
|
556
|
+
"""
|
|
557
|
+
# Triggers the import of all modules containing marker classes in order to
|
|
558
|
+
# register all configurable markers.
|
|
559
|
+
MarkerRegistry.register_builtin_markers()
|
|
560
|
+
|
|
561
|
+
if not isinstance(config, dict) or len(config) not in [1, 2]:
|
|
562
|
+
raise InvalidMarkerConfig(
|
|
563
|
+
"To configure a marker, please define a dictionary that maps a "
|
|
564
|
+
"single operator tag or a single condition tag to the "
|
|
565
|
+
"corresponding parameter configuration or a list of marker "
|
|
566
|
+
"configurations, respectively. "
|
|
567
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
description = config.pop("description", None)
|
|
571
|
+
tag = next(iter(config))
|
|
572
|
+
sub_marker_config = config[tag]
|
|
573
|
+
|
|
574
|
+
tag, _ = MarkerRegistry.get_non_negated_tag(tag_or_negated_tag=tag)
|
|
575
|
+
if tag in MarkerRegistry.operator_tag_to_marker_class:
|
|
576
|
+
return OperatorMarker.from_tag_and_sub_config(
|
|
577
|
+
tag=tag,
|
|
578
|
+
sub_config=sub_marker_config,
|
|
579
|
+
name=name,
|
|
580
|
+
description=description,
|
|
581
|
+
)
|
|
582
|
+
elif tag in MarkerRegistry.condition_tag_to_marker_class:
|
|
583
|
+
return ConditionMarker.from_tag_and_sub_config(
|
|
584
|
+
tag=tag,
|
|
585
|
+
sub_config=sub_marker_config,
|
|
586
|
+
name=name,
|
|
587
|
+
description=description,
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
raise InvalidMarkerConfig(
|
|
591
|
+
f"Expected a marker configuration with a key that specifies"
|
|
592
|
+
f" an operator or a condition but found {tag}. "
|
|
593
|
+
f"Available conditions and operators are: "
|
|
594
|
+
f"{sorted(MarkerRegistry.all_tags)}. "
|
|
595
|
+
f"Refer to the docs for more information: {DOCS_URL_MARKERS} "
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
async def evaluate_trackers(
|
|
599
|
+
self,
|
|
600
|
+
trackers: AsyncIterator[Optional[DialogueStateTracker]],
|
|
601
|
+
output_file: Path,
|
|
602
|
+
session_stats_file: Optional[Path] = None,
|
|
603
|
+
overall_stats_file: Optional[Path] = None,
|
|
604
|
+
) -> None:
|
|
605
|
+
"""Collect markers for each dialogue in each tracker loaded.
|
|
606
|
+
|
|
607
|
+
Args:
|
|
608
|
+
trackers: An iterator over the trackers from which we want to extract
|
|
609
|
+
markers.
|
|
610
|
+
output_file: Path to write out the extracted markers.
|
|
611
|
+
session_stats_file: (Optional) Path to write out statistics about the
|
|
612
|
+
extracted markers for each session separately.
|
|
613
|
+
overall_stats_file: (Optional) Path to write out statistics about the
|
|
614
|
+
markers extracted from all session data.
|
|
615
|
+
|
|
616
|
+
Raises:
|
|
617
|
+
`FileExistsError` if any of the specified files already exists
|
|
618
|
+
`NotADirectoryError` if any of the specified files is supposed to be
|
|
619
|
+
contained in a directory that does not exist
|
|
620
|
+
"""
|
|
621
|
+
# Check files and folders before doing the costly swipe over the trackers:
|
|
622
|
+
for path in [session_stats_file, overall_stats_file, output_file]:
|
|
623
|
+
if path is not None and path.is_file():
|
|
624
|
+
raise FileExistsError(f"Expected that no file {path} already exists.")
|
|
625
|
+
if path is not None and not path.parent.is_dir():
|
|
626
|
+
raise NotADirectoryError(f"Expected directory {path.parent} to exist.")
|
|
627
|
+
|
|
628
|
+
# Apply marker to each session stored in each tracker and save the results.
|
|
629
|
+
processed_trackers: Dict[Text, List[SessionEvaluation]] = {}
|
|
630
|
+
async for tracker in trackers:
|
|
631
|
+
if tracker:
|
|
632
|
+
tracker_result = self.evaluate_events(tracker.events)
|
|
633
|
+
processed_trackers[tracker.sender_id] = tracker_result
|
|
634
|
+
|
|
635
|
+
processed_trackers_count = len(processed_trackers)
|
|
636
|
+
telemetry.track_markers_extracted(processed_trackers_count)
|
|
637
|
+
Marker._save_results(output_file, processed_trackers)
|
|
638
|
+
|
|
639
|
+
# Compute and write statistics if requested.
|
|
640
|
+
if session_stats_file or overall_stats_file:
|
|
641
|
+
from rasa.core.evaluation.marker_stats import MarkerStatistics
|
|
642
|
+
|
|
643
|
+
stats = MarkerStatistics()
|
|
644
|
+
for sender_id, tracker_result in processed_trackers.items():
|
|
645
|
+
for session_idx, session_result in enumerate(tracker_result):
|
|
646
|
+
stats.process(
|
|
647
|
+
sender_id=sender_id,
|
|
648
|
+
session_idx=session_idx,
|
|
649
|
+
meta_data_on_relevant_events_per_marker=session_result,
|
|
650
|
+
)
|
|
651
|
+
|
|
652
|
+
telemetry.track_markers_stats_computed(processed_trackers_count)
|
|
653
|
+
if overall_stats_file:
|
|
654
|
+
stats.overall_statistic_to_csv(path=overall_stats_file)
|
|
655
|
+
if session_stats_file:
|
|
656
|
+
stats.per_session_statistics_to_csv(path=session_stats_file)
|
|
657
|
+
|
|
658
|
+
@staticmethod
|
|
659
|
+
def _save_results(path: Path, results: Dict[Text, List[SessionEvaluation]]) -> None:
|
|
660
|
+
"""Save extracted marker results as CSV to specified path.
|
|
661
|
+
|
|
662
|
+
Args:
|
|
663
|
+
path: Path to write out the extracted markers.
|
|
664
|
+
results: Extracted markers from a selection of trackers.
|
|
665
|
+
"""
|
|
666
|
+
with path.open(mode="w") as f:
|
|
667
|
+
table_writer = csv.writer(f)
|
|
668
|
+
table_writer.writerow(
|
|
669
|
+
[
|
|
670
|
+
"sender_id",
|
|
671
|
+
"session_idx",
|
|
672
|
+
"marker",
|
|
673
|
+
"event_idx",
|
|
674
|
+
"num_preceding_user_turns",
|
|
675
|
+
]
|
|
676
|
+
)
|
|
677
|
+
for sender_id, results_per_session in results.items():
|
|
678
|
+
for session_idx, session_result in enumerate(results_per_session):
|
|
679
|
+
Marker._write_relevant_events(
|
|
680
|
+
table_writer, sender_id, session_idx, session_result
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
@staticmethod
|
|
684
|
+
def _write_relevant_events(
|
|
685
|
+
writer: WriteRow, sender_id: Text, session_idx: int, session: SessionEvaluation
|
|
686
|
+
) -> None:
|
|
687
|
+
for marker_name, meta_data_per_relevant_event in session.items():
|
|
688
|
+
for event_meta_data in meta_data_per_relevant_event:
|
|
689
|
+
writer.writerow(
|
|
690
|
+
[
|
|
691
|
+
sender_id,
|
|
692
|
+
str(session_idx),
|
|
693
|
+
marker_name,
|
|
694
|
+
str(event_meta_data.idx),
|
|
695
|
+
str(event_meta_data.preceding_user_turns),
|
|
696
|
+
]
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
class OperatorMarker(Marker, ABC):
|
|
701
|
+
"""Combines several markers into one."""
|
|
702
|
+
|
|
703
|
+
def __init__(
|
|
704
|
+
self,
|
|
705
|
+
markers: List[Marker],
|
|
706
|
+
negated: bool = False,
|
|
707
|
+
name: Optional[Text] = None,
|
|
708
|
+
description: Optional[Text] = None,
|
|
709
|
+
) -> None:
|
|
710
|
+
"""Instantiates a marker.
|
|
711
|
+
|
|
712
|
+
Args:
|
|
713
|
+
markers: the list of markers to combine
|
|
714
|
+
negated: whether this marker should be negated (i.e. a negated marker
|
|
715
|
+
applies if and only if the non-negated marker does not apply)
|
|
716
|
+
name: a custom name that can be used to replace the default string
|
|
717
|
+
conversion of this marker
|
|
718
|
+
description: an optional description of the marker. It is not used
|
|
719
|
+
internally but can be used to document the marker.
|
|
720
|
+
|
|
721
|
+
Raises:
|
|
722
|
+
`InvalidMarkerConfig` if the given number of sub-markers does not match
|
|
723
|
+
the expected number of sub-markers
|
|
724
|
+
"""
|
|
725
|
+
super().__init__(name=name, negated=negated, description=description)
|
|
726
|
+
self.sub_markers: List[Marker] = markers
|
|
727
|
+
expected_num = self.expected_number_of_sub_markers()
|
|
728
|
+
if expected_num is not None and len(markers) != expected_num:
|
|
729
|
+
raise InvalidMarkerConfig(
|
|
730
|
+
f"Expected {expected_num} sub-marker(s) to be specified for marker "
|
|
731
|
+
f"'{self}' ({self.get_tag()}) but found {len(markers)}. "
|
|
732
|
+
f"Please adapt your configuration so that there are exactly "
|
|
733
|
+
f"{expected_num} sub-markers. "
|
|
734
|
+
)
|
|
735
|
+
elif len(markers) == 0:
|
|
736
|
+
raise InvalidMarkerConfig(
|
|
737
|
+
f"Expected some sub-markers to be specified for {self} but "
|
|
738
|
+
f"found none. Please adapt your configuration so that there is "
|
|
739
|
+
f"at least one sub-marker. "
|
|
740
|
+
)
|
|
741
|
+
|
|
742
|
+
@staticmethod
|
|
743
|
+
def expected_number_of_sub_markers() -> Optional[int]:
|
|
744
|
+
"""Returns the expected number of sub-markers (if there is any)."""
|
|
745
|
+
return None
|
|
746
|
+
|
|
747
|
+
def _to_str_with(self, tag: Text) -> Text:
|
|
748
|
+
marker_str = ", ".join(str(marker) for marker in self.sub_markers)
|
|
749
|
+
return f"{tag}({marker_str})"
|
|
750
|
+
|
|
751
|
+
def track(self, event: Event) -> None:
|
|
752
|
+
"""Updates the marker according to the given event.
|
|
753
|
+
|
|
754
|
+
All sub-markers will be updated before the compound marker itself is updated.
|
|
755
|
+
|
|
756
|
+
Args:
|
|
757
|
+
event: the next event of the conversation
|
|
758
|
+
"""
|
|
759
|
+
for marker in self.sub_markers:
|
|
760
|
+
marker.track(event)
|
|
761
|
+
super().track(event)
|
|
762
|
+
|
|
763
|
+
def flatten(self) -> Iterator[Marker]:
|
|
764
|
+
"""Returns an iterator over all included markers, plus this marker itself.
|
|
765
|
+
|
|
766
|
+
Returns:
|
|
767
|
+
an iterator over all markers that are part of this marker
|
|
768
|
+
"""
|
|
769
|
+
for marker in self.sub_markers:
|
|
770
|
+
for sub_marker in marker.flatten():
|
|
771
|
+
yield sub_marker
|
|
772
|
+
yield self
|
|
773
|
+
|
|
774
|
+
def reset(self) -> None:
|
|
775
|
+
"""Resets the history of this marker and all its sub-markers."""
|
|
776
|
+
for marker in self.sub_markers:
|
|
777
|
+
marker.reset()
|
|
778
|
+
super().reset()
|
|
779
|
+
|
|
780
|
+
def validate_against_domain(self, domain: Domain) -> bool:
|
|
781
|
+
"""Checks that this marker (and its children) refer to entries in the domain.
|
|
782
|
+
|
|
783
|
+
Args:
|
|
784
|
+
domain: The domain to check against
|
|
785
|
+
"""
|
|
786
|
+
return all(
|
|
787
|
+
marker.validate_against_domain(domain) for marker in self.sub_markers
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
def max_depth(self) -> int:
|
|
791
|
+
"""Gets the maximum depth from this point in the marker tree."""
|
|
792
|
+
return 1 + max(child.max_depth() for child in self.sub_markers)
|
|
793
|
+
|
|
794
|
+
@staticmethod
|
|
795
|
+
def from_tag_and_sub_config(
|
|
796
|
+
tag: Text,
|
|
797
|
+
sub_config: Any,
|
|
798
|
+
name: Optional[Text] = None,
|
|
799
|
+
description: Optional[Text] = None,
|
|
800
|
+
) -> OperatorMarker:
|
|
801
|
+
"""Creates an operator marker from the given config.
|
|
802
|
+
|
|
803
|
+
The configuration must consist of a list of marker configurations.
|
|
804
|
+
See `Marker.from_config` for more details.
|
|
805
|
+
|
|
806
|
+
Args:
|
|
807
|
+
tag: the tag identifying an operator
|
|
808
|
+
sub_config: a list of marker configs
|
|
809
|
+
name: an optional custom name to be attached to the resulting marker
|
|
810
|
+
description: an optional description of the marker
|
|
811
|
+
Returns:
|
|
812
|
+
the configured operator marker
|
|
813
|
+
Raises:
|
|
814
|
+
`InvalidMarkerConfig` if the given config or the tag are not well-defined
|
|
815
|
+
"""
|
|
816
|
+
positive_tag, is_negation = MarkerRegistry.get_non_negated_tag(tag)
|
|
817
|
+
operator_class = MarkerRegistry.operator_tag_to_marker_class.get(positive_tag)
|
|
818
|
+
if operator_class is None:
|
|
819
|
+
raise InvalidConfigException(f"Unknown operator '{tag}'.")
|
|
820
|
+
|
|
821
|
+
if not isinstance(sub_config, list):
|
|
822
|
+
raise InvalidMarkerConfig(
|
|
823
|
+
f"Expected a list of sub-marker configurations under {tag}."
|
|
824
|
+
)
|
|
825
|
+
collected_sub_markers: List[Marker] = []
|
|
826
|
+
for sub_marker_config in sub_config:
|
|
827
|
+
try:
|
|
828
|
+
sub_marker = Marker.from_config(sub_marker_config)
|
|
829
|
+
except InvalidMarkerConfig as e:
|
|
830
|
+
# we don't re-raise here because the stack trace would only be
|
|
831
|
+
# printed when we run rasa evaluate with --debug flag
|
|
832
|
+
raise InvalidMarkerConfig(
|
|
833
|
+
f"Could not create sub-marker for operator '{tag}' from "
|
|
834
|
+
f"{sub_marker_config}. Reason: {e!s}"
|
|
835
|
+
)
|
|
836
|
+
collected_sub_markers.append(sub_marker)
|
|
837
|
+
try:
|
|
838
|
+
marker = operator_class(markers=collected_sub_markers, negated=is_negation)
|
|
839
|
+
except InvalidMarkerConfig as e:
|
|
840
|
+
# we don't re-raise here because the stack trace would only be
|
|
841
|
+
# printed when we run rasa evaluate with --debug flag
|
|
842
|
+
raise InvalidMarkerConfig(
|
|
843
|
+
f"Could not create operator '{tag}' with sub-markers "
|
|
844
|
+
f"{collected_sub_markers}. Reason: {e!s}"
|
|
845
|
+
)
|
|
846
|
+
marker.name = name
|
|
847
|
+
marker.description = description
|
|
848
|
+
return marker
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
class ConditionMarker(Marker, ABC):
|
|
852
|
+
"""A marker that does not contain any sub-markers."""
|
|
853
|
+
|
|
854
|
+
def __init__(
|
|
855
|
+
self,
|
|
856
|
+
text: Text,
|
|
857
|
+
negated: bool = False,
|
|
858
|
+
name: Optional[Text] = None,
|
|
859
|
+
description: Optional[Text] = None,
|
|
860
|
+
) -> None:
|
|
861
|
+
"""Instantiates an atomic marker.
|
|
862
|
+
|
|
863
|
+
Args:
|
|
864
|
+
text: some text used to decide whether the marker applies
|
|
865
|
+
negated: whether this marker should be negated (i.e. a negated marker
|
|
866
|
+
applies if and only if the non-negated marker does not apply)
|
|
867
|
+
name: a custom name that can be used to replace the default string
|
|
868
|
+
conversion of this marker
|
|
869
|
+
description: an optional description of the marker. It is not used
|
|
870
|
+
internally but can be used to document the marker.
|
|
871
|
+
"""
|
|
872
|
+
super().__init__(name=name, negated=negated)
|
|
873
|
+
self.text = text
|
|
874
|
+
self.description = description
|
|
875
|
+
|
|
876
|
+
def _to_str_with(self, tag: Text) -> Text:
|
|
877
|
+
return f"({tag}: {self.text})"
|
|
878
|
+
|
|
879
|
+
def flatten(self) -> Iterator[ConditionMarker]:
|
|
880
|
+
"""Returns an iterator that just returns this `AtomicMarker`.
|
|
881
|
+
|
|
882
|
+
Returns:
|
|
883
|
+
an iterator over all markers that are part of this marker, i.e. this marker
|
|
884
|
+
"""
|
|
885
|
+
yield self
|
|
886
|
+
|
|
887
|
+
def max_depth(self) -> int:
|
|
888
|
+
"""Gets the maximum depth from this point in the marker tree."""
|
|
889
|
+
return 1
|
|
890
|
+
|
|
891
|
+
@staticmethod
|
|
892
|
+
def from_tag_and_sub_config(
|
|
893
|
+
tag: Text,
|
|
894
|
+
sub_config: Any,
|
|
895
|
+
name: Optional[Text] = None,
|
|
896
|
+
description: Optional[Text] = None,
|
|
897
|
+
) -> ConditionMarker:
|
|
898
|
+
"""Creates an atomic marker from the given config.
|
|
899
|
+
|
|
900
|
+
Args:
|
|
901
|
+
tag: the tag identifying a condition
|
|
902
|
+
sub_config: a single text parameter expected by all condition markers;
|
|
903
|
+
e.g. if the tag is for an `intent_detected` marker then the `config`
|
|
904
|
+
should contain an intent name
|
|
905
|
+
name: a custom name for this marker
|
|
906
|
+
Returns:
|
|
907
|
+
the configured `ConditionMarker`
|
|
908
|
+
Raises:
|
|
909
|
+
`InvalidMarkerConfig` if the given config or the tag are not well-defined
|
|
910
|
+
"""
|
|
911
|
+
positive_tag, is_negation = MarkerRegistry.get_non_negated_tag(tag)
|
|
912
|
+
marker_class = MarkerRegistry.condition_tag_to_marker_class.get(positive_tag)
|
|
913
|
+
if marker_class is None:
|
|
914
|
+
raise InvalidConfigException(f"Unknown condition '{tag}'.")
|
|
915
|
+
|
|
916
|
+
if not isinstance(sub_config, str):
|
|
917
|
+
raise InvalidMarkerConfig(
|
|
918
|
+
f"Expected a text parameter to be specified for marker '{tag}'."
|
|
919
|
+
)
|
|
920
|
+
marker = marker_class(sub_config, negated=is_negation)
|
|
921
|
+
marker.name = name
|
|
922
|
+
marker.description = description
|
|
923
|
+
return marker
|