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,1451 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import inspect
|
|
3
|
+
import logging
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
import typing
|
|
7
|
+
from typing import (
|
|
8
|
+
Optional,
|
|
9
|
+
Callable,
|
|
10
|
+
Text,
|
|
11
|
+
Tuple,
|
|
12
|
+
Dict,
|
|
13
|
+
Type,
|
|
14
|
+
Any,
|
|
15
|
+
Set,
|
|
16
|
+
Union,
|
|
17
|
+
TypeVar,
|
|
18
|
+
List,
|
|
19
|
+
Literal,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import rasa.utils.common
|
|
23
|
+
import structlog
|
|
24
|
+
import typing_utils
|
|
25
|
+
from rasa.core import IntentlessPolicy, ContextualResponseRephraser
|
|
26
|
+
from rasa.core.policies.policy import PolicyPrediction
|
|
27
|
+
from rasa.core.utils import AvailableEndpoints
|
|
28
|
+
from rasa.dialogue_understanding.coexistence.constants import (
|
|
29
|
+
NLU_ENTRY,
|
|
30
|
+
CALM_ENTRY,
|
|
31
|
+
STICKY,
|
|
32
|
+
NON_STICKY,
|
|
33
|
+
)
|
|
34
|
+
from rasa.dialogue_understanding.coexistence.intent_based_router import (
|
|
35
|
+
IntentBasedRouter,
|
|
36
|
+
)
|
|
37
|
+
from rasa.dialogue_understanding.coexistence.llm_based_router import LLMBasedRouter
|
|
38
|
+
from rasa.dialogue_understanding.generator import (
|
|
39
|
+
LLMBasedCommandGenerator,
|
|
40
|
+
)
|
|
41
|
+
from rasa.dialogue_understanding.generator.constants import (
|
|
42
|
+
LLM_CONFIG_KEY,
|
|
43
|
+
FLOW_RETRIEVAL_KEY,
|
|
44
|
+
)
|
|
45
|
+
from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
46
|
+
from rasa.engine.constants import RESERVED_PLACEHOLDERS
|
|
47
|
+
from rasa.engine.exceptions import GraphSchemaValidationException
|
|
48
|
+
from rasa.engine.graph import (
|
|
49
|
+
GraphSchema,
|
|
50
|
+
GraphComponent,
|
|
51
|
+
SchemaNode,
|
|
52
|
+
ExecutionContext,
|
|
53
|
+
GraphModelConfiguration,
|
|
54
|
+
)
|
|
55
|
+
from rasa.engine.storage.resource import Resource
|
|
56
|
+
from rasa.engine.storage.storage import ModelStorage, ModelMetadata
|
|
57
|
+
from rasa.engine.training.fingerprinting import Fingerprintable
|
|
58
|
+
from rasa.shared.constants import (
|
|
59
|
+
DOCS_URL_GRAPH_COMPONENTS,
|
|
60
|
+
ROUTE_TO_CALM_SLOT,
|
|
61
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
62
|
+
API_BASE_CONFIG_KEY,
|
|
63
|
+
DEPLOYMENT_CONFIG_KEY,
|
|
64
|
+
API_VERSION_CONFIG_KEY,
|
|
65
|
+
API_KEY,
|
|
66
|
+
AWS_REGION_NAME_CONFIG_KEY,
|
|
67
|
+
MODEL_GROUP_ID_CONFIG_KEY,
|
|
68
|
+
ROUTER_CONFIG_KEY,
|
|
69
|
+
MODELS_CONFIG_KEY,
|
|
70
|
+
MODEL_GROUP_CONFIG_KEY,
|
|
71
|
+
ROUTING_STRATEGY_CONFIG_KEY,
|
|
72
|
+
VALID_ROUTING_STRATEGIES,
|
|
73
|
+
ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE,
|
|
74
|
+
ROUTING_STRATEGIES_NOT_REQUIRING_CACHE,
|
|
75
|
+
REDIS_HOST_CONFIG_KEY,
|
|
76
|
+
AWS_ACCESS_KEY_ID_CONFIG_KEY,
|
|
77
|
+
AWS_SECRET_ACCESS_KEY_CONFIG_KEY,
|
|
78
|
+
AWS_SESSION_TOKEN_CONFIG_KEY,
|
|
79
|
+
SENSITIVE_DATA,
|
|
80
|
+
USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY,
|
|
81
|
+
API_TYPE_CONFIG_KEY,
|
|
82
|
+
VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY,
|
|
83
|
+
PROVIDER_CONFIG_KEY,
|
|
84
|
+
)
|
|
85
|
+
from rasa.shared.core.constants import ACTION_RESET_ROUTING, ACTION_TRIGGER_CHITCHAT
|
|
86
|
+
from rasa.shared.core.domain import Domain
|
|
87
|
+
from rasa.shared.core.flows import FlowsList, Flow
|
|
88
|
+
from rasa.shared.core.slots import Slot
|
|
89
|
+
from rasa.shared.exceptions import RasaException
|
|
90
|
+
from rasa.shared.nlu.training_data.message import Message
|
|
91
|
+
|
|
92
|
+
TypeAnnotation = Union[TypeVar, Text, Type, Optional[AvailableEndpoints]]
|
|
93
|
+
|
|
94
|
+
structlogger = structlog.get_logger()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclasses.dataclass
|
|
98
|
+
class ParameterInfo:
|
|
99
|
+
"""Stores metadata about a function parameter."""
|
|
100
|
+
|
|
101
|
+
type_annotation: TypeAnnotation
|
|
102
|
+
# `True` if we have a parameter like `**kwargs`
|
|
103
|
+
is_variable_length_keyword_arg: bool
|
|
104
|
+
has_default: bool
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
KEYWORDS_EXPECTED_TYPES: Dict[Text, TypeAnnotation] = {
|
|
108
|
+
"resource": Resource,
|
|
109
|
+
"execution_context": ExecutionContext,
|
|
110
|
+
"model_storage": ModelStorage,
|
|
111
|
+
"config": Dict[Text, Any],
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def validate(model_configuration: GraphModelConfiguration) -> None:
|
|
116
|
+
"""Validates a graph schema.
|
|
117
|
+
|
|
118
|
+
This tries to validate that the graph structure is correct (e.g. all nodes pass the
|
|
119
|
+
correct things into each other) as well as validates the individual graph
|
|
120
|
+
components.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
model_configuration: The model configuration (schemas, language, etc.)
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
GraphSchemaValidationException: If the validation failed.
|
|
127
|
+
"""
|
|
128
|
+
_validate(model_configuration.train_schema, True, model_configuration.language)
|
|
129
|
+
_validate(model_configuration.predict_schema, False, model_configuration.language)
|
|
130
|
+
|
|
131
|
+
_validate_prediction_targets(
|
|
132
|
+
model_configuration.predict_schema,
|
|
133
|
+
core_target=model_configuration.core_target,
|
|
134
|
+
nlu_target=model_configuration.nlu_target,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _validate(
|
|
139
|
+
schema: GraphSchema, is_train_graph: bool, language: Optional[Text]
|
|
140
|
+
) -> None:
|
|
141
|
+
_validate_cycle(schema)
|
|
142
|
+
|
|
143
|
+
for node_name, node in schema.nodes.items():
|
|
144
|
+
_validate_interface_usage(node)
|
|
145
|
+
_validate_supported_languages(language, node)
|
|
146
|
+
_validate_required_packages(node)
|
|
147
|
+
|
|
148
|
+
run_fn_params, run_fn_return_type = _get_parameter_information(
|
|
149
|
+
node.uses, node.fn
|
|
150
|
+
)
|
|
151
|
+
_validate_run_fn(node, run_fn_params, run_fn_return_type, is_train_graph)
|
|
152
|
+
|
|
153
|
+
create_fn_params, _ = _get_parameter_information(
|
|
154
|
+
node.uses, node.constructor_name
|
|
155
|
+
)
|
|
156
|
+
_validate_constructor(node, create_fn_params)
|
|
157
|
+
|
|
158
|
+
_validate_needs(node, schema, create_fn_params, run_fn_params)
|
|
159
|
+
|
|
160
|
+
_validate_required_components(schema)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _validate_prediction_targets(
|
|
164
|
+
schema: GraphSchema, core_target: Optional[Text], nlu_target: Text
|
|
165
|
+
) -> None:
|
|
166
|
+
if not nlu_target:
|
|
167
|
+
raise GraphSchemaValidationException(
|
|
168
|
+
"Graph schema specifies no target for the 'nlu_target'. It is required "
|
|
169
|
+
"for a prediction graph to specify this. Please choose a valid node "
|
|
170
|
+
"name for this."
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
_validate_target(nlu_target, "NLU", List[Message], schema)
|
|
174
|
+
|
|
175
|
+
if core_target:
|
|
176
|
+
_validate_target(core_target, "Core", PolicyPrediction, schema)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _validate_target(
|
|
180
|
+
target_name: Text, target_type: Text, expected_type: Type, schema: GraphSchema
|
|
181
|
+
) -> None:
|
|
182
|
+
if target_name not in schema.nodes:
|
|
183
|
+
raise GraphSchemaValidationException(
|
|
184
|
+
f"Graph schema specifies invalid {target_type} target '{target_name}'. "
|
|
185
|
+
f"Please make sure specify a valid node name as target."
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if any(target_name in node.needs.values() for node in schema.nodes.values()):
|
|
189
|
+
raise GraphSchemaValidationException(
|
|
190
|
+
f"One graph node uses the {target_type} target '{target_name}' as input. "
|
|
191
|
+
f"This is not allowed as NLU prediction and Core prediction are run "
|
|
192
|
+
f"separately."
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
target_node = schema.nodes[target_name]
|
|
196
|
+
_, target_return_type = _get_parameter_information(target_node.uses, target_node.fn)
|
|
197
|
+
|
|
198
|
+
if not typing_utils.issubtype(target_return_type, expected_type):
|
|
199
|
+
raise GraphSchemaValidationException(
|
|
200
|
+
f"Your {target_type} model's output component "
|
|
201
|
+
f"'{target_node.uses.__name__}' returns an invalid return "
|
|
202
|
+
f"type '{target_return_type}'. This is not allowed. The {target_type} "
|
|
203
|
+
f"model's last component is expected to return the type '{expected_type}'. "
|
|
204
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _validate_cycle(schema: GraphSchema) -> None:
|
|
209
|
+
for target_name in schema.target_names:
|
|
210
|
+
parents = schema.nodes[target_name].needs.values()
|
|
211
|
+
for parent_name in parents:
|
|
212
|
+
_walk_and_check_for_cycles([], parent_name, schema)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _walk_and_check_for_cycles(
|
|
216
|
+
visited_so_far: List[Text], node_name: Text, schema: GraphSchema
|
|
217
|
+
) -> None:
|
|
218
|
+
if node_name in visited_so_far:
|
|
219
|
+
raise GraphSchemaValidationException(
|
|
220
|
+
f"Node '{node_name}' has itself as dependency. Cycles are not allowed "
|
|
221
|
+
f"in the graph. Please make sure that '{node_name}' does not have itself "
|
|
222
|
+
f"specified in 'needs' and none of '{node_name}'s dependencies have "
|
|
223
|
+
f"'{node_name}' specified in 'needs'."
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
if node_name not in schema.nodes:
|
|
227
|
+
raise GraphSchemaValidationException(
|
|
228
|
+
f"Node '{node_name}' is not part of the graph. Node was expected to be "
|
|
229
|
+
f"present in the graph as it is used by another component."
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
parents = schema.nodes[node_name].needs.values()
|
|
233
|
+
for parent_name in parents:
|
|
234
|
+
if not _is_placeholder_input(parent_name):
|
|
235
|
+
_walk_and_check_for_cycles(
|
|
236
|
+
[*visited_so_far, node_name], parent_name, schema
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _is_placeholder_input(name: Text) -> bool:
|
|
241
|
+
return name in RESERVED_PLACEHOLDERS
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _validate_interface_usage(node: SchemaNode) -> None:
|
|
245
|
+
if not issubclass(node.uses, GraphComponent):
|
|
246
|
+
raise GraphSchemaValidationException(
|
|
247
|
+
f"Your model uses a component with class '{node.uses.__name__}'. "
|
|
248
|
+
f"This class does not implement the '{GraphComponent.__name__}' interface "
|
|
249
|
+
f"and can hence not be run within Rasa Pro. Please use a different "
|
|
250
|
+
f"component or implement the '{GraphComponent}' interface in class "
|
|
251
|
+
f"'{node.uses.__name__}'. "
|
|
252
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _validate_supported_languages(language: Optional[Text], node: SchemaNode) -> None:
|
|
257
|
+
supported_languages = node.uses.supported_languages()
|
|
258
|
+
not_supported_languages = node.uses.not_supported_languages()
|
|
259
|
+
|
|
260
|
+
if supported_languages and not_supported_languages:
|
|
261
|
+
raise RasaException(
|
|
262
|
+
"Only one of `supported_languages` and "
|
|
263
|
+
"`not_supported_languages` can return a value different from `None`."
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
if (
|
|
267
|
+
language
|
|
268
|
+
and supported_languages is not None
|
|
269
|
+
and language not in supported_languages
|
|
270
|
+
):
|
|
271
|
+
raise GraphSchemaValidationException(
|
|
272
|
+
f"The component '{node.uses.__name__}' does not support the currently "
|
|
273
|
+
f"specified language '{language}'."
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
if (
|
|
277
|
+
language
|
|
278
|
+
and not_supported_languages is not None
|
|
279
|
+
and language in not_supported_languages
|
|
280
|
+
):
|
|
281
|
+
raise GraphSchemaValidationException(
|
|
282
|
+
f"The component '{node.uses.__name__}' does not support the currently "
|
|
283
|
+
f"specified language '{language}'."
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _validate_required_packages(node: SchemaNode) -> None:
|
|
288
|
+
missing_packages = rasa.utils.common.find_unavailable_packages(
|
|
289
|
+
node.uses.required_packages()
|
|
290
|
+
)
|
|
291
|
+
if missing_packages:
|
|
292
|
+
raise GraphSchemaValidationException(
|
|
293
|
+
f"Component '{node.uses.__name__}' requires the following packages which "
|
|
294
|
+
f"are currently not installed: {', '.join(missing_packages)}."
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _get_parameter_information(
|
|
299
|
+
uses: Type[GraphComponent], method_name: Text
|
|
300
|
+
) -> Tuple[Dict[Text, ParameterInfo], TypeAnnotation]:
|
|
301
|
+
fn = _get_fn(uses, method_name)
|
|
302
|
+
|
|
303
|
+
type_hints = _get_type_hints(uses, fn)
|
|
304
|
+
return_type = type_hints.pop("return", inspect.Parameter.empty)
|
|
305
|
+
type_hints.pop("cls", None)
|
|
306
|
+
|
|
307
|
+
params = inspect.signature(fn).parameters
|
|
308
|
+
|
|
309
|
+
type_info = {}
|
|
310
|
+
for param_name, type_annotation in type_hints.items():
|
|
311
|
+
inspect_info = params[param_name]
|
|
312
|
+
if inspect_info.kind == inspect.Parameter.VAR_POSITIONAL:
|
|
313
|
+
# We always pass things using keywords so we can ignore the any variable
|
|
314
|
+
# length positional arguments
|
|
315
|
+
continue
|
|
316
|
+
|
|
317
|
+
type_info[param_name] = ParameterInfo(
|
|
318
|
+
type_annotation=type_annotation,
|
|
319
|
+
is_variable_length_keyword_arg=inspect_info.kind
|
|
320
|
+
== inspect.Parameter.VAR_KEYWORD,
|
|
321
|
+
has_default=inspect_info.default != inspect.Parameter.empty,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
return type_info, return_type
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _get_type_hints(
|
|
328
|
+
uses: Type[GraphComponent], fn: Callable
|
|
329
|
+
) -> Dict[Text, TypeAnnotation]:
|
|
330
|
+
try:
|
|
331
|
+
return typing.get_type_hints(fn)
|
|
332
|
+
except NameError as e:
|
|
333
|
+
logging.debug(
|
|
334
|
+
f"Failed to retrieve type annotations for component "
|
|
335
|
+
f"'{uses.__name__}' due to error:\n{e}"
|
|
336
|
+
)
|
|
337
|
+
raise GraphSchemaValidationException(
|
|
338
|
+
f"Your model uses a component '{uses.__name__}' which has "
|
|
339
|
+
f"type annotations in its method '{fn.__name__}' which failed to be "
|
|
340
|
+
f"retrieved. Please make sure remove any forward "
|
|
341
|
+
f"reference by removing the quotes around the type "
|
|
342
|
+
f"(e.g. 'def foo() -> \"int\"' becomes 'def foo() -> int'. and make sure "
|
|
343
|
+
f"all type annotations can be resolved during runtime. Note that you might "
|
|
344
|
+
f"need to do a 'from __future__ import annotations' to avoid forward "
|
|
345
|
+
f"references."
|
|
346
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _get_fn(uses: Type[GraphComponent], method_name: Text) -> Callable:
|
|
351
|
+
fn = getattr(uses, method_name, None)
|
|
352
|
+
if fn is None:
|
|
353
|
+
raise GraphSchemaValidationException(
|
|
354
|
+
f"Your model uses a graph component '{uses.__name__}' which does not "
|
|
355
|
+
f"have the required "
|
|
356
|
+
f"method '{method_name}'. Please make sure you're either using "
|
|
357
|
+
f"the right component or that your component is registered with the "
|
|
358
|
+
f"correct component type."
|
|
359
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
360
|
+
)
|
|
361
|
+
return fn
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def _validate_run_fn(
|
|
365
|
+
node: SchemaNode,
|
|
366
|
+
run_fn_params: Dict[Text, ParameterInfo],
|
|
367
|
+
run_fn_return_type: TypeAnnotation,
|
|
368
|
+
is_train_graph: bool,
|
|
369
|
+
) -> None:
|
|
370
|
+
_validate_types_of_reserved_keywords(run_fn_params, node, node.fn)
|
|
371
|
+
_validate_run_fn_return_type(node, run_fn_return_type, is_train_graph)
|
|
372
|
+
|
|
373
|
+
for param_name in _required_args(run_fn_params):
|
|
374
|
+
if param_name not in node.needs:
|
|
375
|
+
raise GraphSchemaValidationException(
|
|
376
|
+
f"Your model uses a component '{node.uses.__name__}' which "
|
|
377
|
+
f"needs the param '{param_name}' to be provided to its method "
|
|
378
|
+
f"'{node.fn}'. Please make sure that you registered "
|
|
379
|
+
f"your component correctly and and that your model configuration is "
|
|
380
|
+
f"valid."
|
|
381
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def _required_args(fn_params: Dict[Text, ParameterInfo]) -> Set[Text]:
|
|
386
|
+
keywords = set(KEYWORDS_EXPECTED_TYPES)
|
|
387
|
+
return {
|
|
388
|
+
param_name
|
|
389
|
+
for param_name, param in fn_params.items()
|
|
390
|
+
if not param.has_default
|
|
391
|
+
and not param.is_variable_length_keyword_arg
|
|
392
|
+
and param_name not in keywords
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _validate_run_fn_return_type(
|
|
397
|
+
node: SchemaNode, return_type: Type, is_training: bool
|
|
398
|
+
) -> None:
|
|
399
|
+
if return_type == inspect.Parameter.empty:
|
|
400
|
+
raise GraphSchemaValidationException(
|
|
401
|
+
f"Your model uses a component '{node.uses.__name__}' whose "
|
|
402
|
+
f"method '{node.fn}' does not have a type annotation for "
|
|
403
|
+
f"its return value. Type annotations are required for all "
|
|
404
|
+
f"components to validate your model's structure."
|
|
405
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
# TODO: Handle forward references here
|
|
409
|
+
if typing_utils.issubtype(return_type, list):
|
|
410
|
+
return_type = typing_utils.get_args(return_type)[0]
|
|
411
|
+
|
|
412
|
+
if is_training and not isinstance(return_type, Fingerprintable):
|
|
413
|
+
raise GraphSchemaValidationException(
|
|
414
|
+
f"Your model uses a component '{node.uses.__name__}' whose method "
|
|
415
|
+
f"'{node.fn}' does not return a fingerprintable "
|
|
416
|
+
f"output. This is required for proper caching between model trainings. "
|
|
417
|
+
f"Please make sure you're using a return type which implements the "
|
|
418
|
+
f"'{Fingerprintable.__name__}' protocol."
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def _validate_types_of_reserved_keywords(
|
|
423
|
+
params: Dict[Text, ParameterInfo], node: SchemaNode, fn_name: Text
|
|
424
|
+
) -> None:
|
|
425
|
+
for param_name, param in params.items():
|
|
426
|
+
if param_name in KEYWORDS_EXPECTED_TYPES:
|
|
427
|
+
if not typing_utils.issubtype(
|
|
428
|
+
param.type_annotation, KEYWORDS_EXPECTED_TYPES[param_name]
|
|
429
|
+
):
|
|
430
|
+
raise GraphSchemaValidationException(
|
|
431
|
+
f"Your model uses a component '{node.uses.__name__}' which has an "
|
|
432
|
+
f"incompatible type '{param.type_annotation}' for "
|
|
433
|
+
f"the '{param_name}' parameter in its '{fn_name}' method. "
|
|
434
|
+
f"The expected type is '{KEYWORDS_EXPECTED_TYPES[param_name]}'."
|
|
435
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def _validate_constructor(
|
|
440
|
+
node: SchemaNode, create_fn_params: Dict[Text, ParameterInfo]
|
|
441
|
+
) -> None:
|
|
442
|
+
_validate_types_of_reserved_keywords(create_fn_params, node, node.constructor_name)
|
|
443
|
+
|
|
444
|
+
required_args = _required_args(create_fn_params)
|
|
445
|
+
|
|
446
|
+
if required_args and node.eager:
|
|
447
|
+
raise GraphSchemaValidationException(
|
|
448
|
+
f"Your model uses a component '{node.uses.__name__}' which has a "
|
|
449
|
+
f"method '{node.constructor_name}' which has required parameters "
|
|
450
|
+
f"('{', '.join(required_args)}'). "
|
|
451
|
+
f"Extra parameters can only be supplied to the constructor method which is "
|
|
452
|
+
f"used during training."
|
|
453
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
for param_name in _required_args(create_fn_params):
|
|
457
|
+
if not node.eager and param_name not in node.needs:
|
|
458
|
+
raise GraphSchemaValidationException(
|
|
459
|
+
f"Your model uses a component '{node.uses.__name__}' which "
|
|
460
|
+
f"needs the param '{param_name}' to be provided to its method "
|
|
461
|
+
f"'{node.constructor_name}'. Please make sure that you registered "
|
|
462
|
+
f"your component correctly and and that your model configuration is "
|
|
463
|
+
f"valid."
|
|
464
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def _validate_needs(
|
|
469
|
+
node: SchemaNode,
|
|
470
|
+
graph: GraphSchema,
|
|
471
|
+
create_fn_params: Dict[Text, ParameterInfo],
|
|
472
|
+
run_fn_params: Dict[Text, ParameterInfo],
|
|
473
|
+
) -> None:
|
|
474
|
+
available_args, has_kwargs = _get_available_args(
|
|
475
|
+
node, create_fn_params, run_fn_params
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
for param_name, parent_name in node.needs.items():
|
|
479
|
+
if not has_kwargs and param_name not in available_args:
|
|
480
|
+
raise GraphSchemaValidationException(
|
|
481
|
+
f"Your model uses a component '{node.uses.__name__}' which is "
|
|
482
|
+
f"supposed to retrieve a value for the "
|
|
483
|
+
f"param '{param_name}' although "
|
|
484
|
+
f"its method '{node.fn}' does not accept a parameter with this "
|
|
485
|
+
f"name. Please make sure that you registered "
|
|
486
|
+
f"your component correctly and and that your model configuration is "
|
|
487
|
+
f"valid."
|
|
488
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
if not _is_placeholder_input(parent_name) and parent_name not in graph.nodes:
|
|
492
|
+
raise GraphSchemaValidationException(
|
|
493
|
+
f"Missing graph component '{parent_name}'."
|
|
494
|
+
f"Your model uses a component '{node.uses.__name__}' which expects "
|
|
495
|
+
f"input from the missing component. The component is missing from "
|
|
496
|
+
f"your model configuration. Please make sure that you registered "
|
|
497
|
+
f"your component correctly and and that your model configuration is "
|
|
498
|
+
f"valid."
|
|
499
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
required_type = available_args.get(param_name)
|
|
503
|
+
|
|
504
|
+
if not has_kwargs and required_type is not None:
|
|
505
|
+
parent = None
|
|
506
|
+
if _is_placeholder_input(parent_name):
|
|
507
|
+
parent_return_type: TypeAnnotation
|
|
508
|
+
parent_return_type = RESERVED_PLACEHOLDERS[parent_name] # type: ignore
|
|
509
|
+
else:
|
|
510
|
+
parent = graph.nodes[parent_name]
|
|
511
|
+
_, parent_return_type = _get_parameter_information(
|
|
512
|
+
parent.uses, parent.fn
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
_validate_parent_return_type(
|
|
516
|
+
node, parent, parent_return_type, required_type.type_annotation
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def _get_available_args(
|
|
521
|
+
node: SchemaNode,
|
|
522
|
+
create_fn_params: Dict[Text, ParameterInfo],
|
|
523
|
+
run_fn_params: Dict[Text, ParameterInfo],
|
|
524
|
+
) -> Tuple[Dict[Text, ParameterInfo], bool]:
|
|
525
|
+
has_kwargs = any(
|
|
526
|
+
param.is_variable_length_keyword_arg for param in run_fn_params.values()
|
|
527
|
+
)
|
|
528
|
+
available_args = run_fn_params.copy()
|
|
529
|
+
if node.eager is False:
|
|
530
|
+
has_kwargs = has_kwargs or any(
|
|
531
|
+
param.is_variable_length_keyword_arg for param in create_fn_params.values()
|
|
532
|
+
)
|
|
533
|
+
available_args.update(create_fn_params)
|
|
534
|
+
return available_args, has_kwargs
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def _validate_parent_return_type(
|
|
538
|
+
node: SchemaNode,
|
|
539
|
+
parent_node: Optional[SchemaNode],
|
|
540
|
+
parent_return_type: TypeAnnotation,
|
|
541
|
+
required_type: TypeAnnotation,
|
|
542
|
+
) -> None:
|
|
543
|
+
if not typing_utils.issubtype(parent_return_type, required_type):
|
|
544
|
+
parent_node_text = ""
|
|
545
|
+
if parent_node:
|
|
546
|
+
parent_node_text = f" by the component '{parent_node.uses.__name__}'"
|
|
547
|
+
|
|
548
|
+
raise GraphSchemaValidationException(
|
|
549
|
+
f"Your component '{node.uses.__name__}' expects an input of type "
|
|
550
|
+
f"'{required_type}' but it receives an input of type '{parent_return_type}'"
|
|
551
|
+
f"{parent_node_text}. "
|
|
552
|
+
f"Please make sure that you registered "
|
|
553
|
+
f"your component correctly and and that your model configuration is "
|
|
554
|
+
f"valid."
|
|
555
|
+
f"See {DOCS_URL_GRAPH_COMPONENTS} for more information."
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def _validate_required_components(schema: GraphSchema) -> None:
|
|
560
|
+
unmet_requirements: Dict[Type, Set[Text]] = dict()
|
|
561
|
+
for target_name in schema.target_names:
|
|
562
|
+
unmet_requirements_for_target, _ = _recursively_check_required_components(
|
|
563
|
+
node_name=target_name, schema=schema
|
|
564
|
+
)
|
|
565
|
+
for component_type, node_names in unmet_requirements_for_target.items():
|
|
566
|
+
unmet_requirements.setdefault(component_type, set()).update(node_names)
|
|
567
|
+
if unmet_requirements:
|
|
568
|
+
errors = "\n".join(
|
|
569
|
+
[
|
|
570
|
+
f"The following components require a {component_type.__name__}: "
|
|
571
|
+
f"{', '.join(sorted(required_by))}. "
|
|
572
|
+
for component_type, required_by in unmet_requirements.items()
|
|
573
|
+
]
|
|
574
|
+
)
|
|
575
|
+
num_nodes = len(
|
|
576
|
+
set(
|
|
577
|
+
node_name
|
|
578
|
+
for required_by in unmet_requirements.values()
|
|
579
|
+
for node_name in required_by
|
|
580
|
+
)
|
|
581
|
+
)
|
|
582
|
+
raise GraphSchemaValidationException(
|
|
583
|
+
f"{num_nodes} components are missing required components which have to "
|
|
584
|
+
f"run before themselves:\n"
|
|
585
|
+
f"{errors}"
|
|
586
|
+
f"Please add the required components to your model configuration."
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def _recursively_check_required_components(
|
|
591
|
+
node_name: Text, schema: GraphSchema
|
|
592
|
+
) -> Tuple[Dict[Type, Set[Text]], Set[Type]]:
|
|
593
|
+
"""Collects unmet requirements and types used in the subtree rooted at `node_name`.
|
|
594
|
+
|
|
595
|
+
Args:
|
|
596
|
+
schema: the graph schema
|
|
597
|
+
node_name: the name of the root of the subtree
|
|
598
|
+
Returns:
|
|
599
|
+
unmet requirements, i.e. a mapping from component types to names of nodes that
|
|
600
|
+
are contained in the subtree rooted at `schema_node` that require that component
|
|
601
|
+
type but can't find it in their respective subtrees and
|
|
602
|
+
a set containing all component types of nodes that are ancestors of the
|
|
603
|
+
`schema_node` (or of the`schema_node` itself)
|
|
604
|
+
"""
|
|
605
|
+
schema_node = schema.nodes[node_name]
|
|
606
|
+
|
|
607
|
+
unmet_requirements: Dict[Type, Set[Text]] = dict()
|
|
608
|
+
component_types = set()
|
|
609
|
+
|
|
610
|
+
# collect all component types used by ancestors and their unmet requirements
|
|
611
|
+
for parent_node_name in schema_node.needs.values():
|
|
612
|
+
if _is_placeholder_input(parent_node_name):
|
|
613
|
+
continue
|
|
614
|
+
(
|
|
615
|
+
unmet_requirements_of_ancestors,
|
|
616
|
+
ancestor_types,
|
|
617
|
+
) = _recursively_check_required_components(
|
|
618
|
+
node_name=parent_node_name, schema=schema
|
|
619
|
+
)
|
|
620
|
+
for _type, nodes in unmet_requirements_of_ancestors.items():
|
|
621
|
+
unmet_requirements.setdefault(_type, set()).update(nodes)
|
|
622
|
+
component_types.update(ancestor_types)
|
|
623
|
+
|
|
624
|
+
# check which requirements of the `schema_node` are not fulfilled by
|
|
625
|
+
# comparing its requirements with the types found so far among the ancestor nodes
|
|
626
|
+
unmet_requirements_of_current_node = set(
|
|
627
|
+
required
|
|
628
|
+
for required in schema_node.uses.required_components()
|
|
629
|
+
if not any(
|
|
630
|
+
issubclass(used_subtype, required) for used_subtype in component_types
|
|
631
|
+
)
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
# add the unmet requirements and the type of the `schema_node`
|
|
635
|
+
for component_type in unmet_requirements_of_current_node:
|
|
636
|
+
unmet_requirements.setdefault(component_type, set()).add(node_name)
|
|
637
|
+
component_types.add(schema_node.uses)
|
|
638
|
+
|
|
639
|
+
return unmet_requirements, component_types
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def validate_flow_component_dependencies(
|
|
643
|
+
flows: FlowsList, model_configuration: GraphModelConfiguration
|
|
644
|
+
) -> None:
|
|
645
|
+
if (pattern_chitchat := flows.flow_by_id(FLOW_PATTERN_CHITCHAT)) is not None:
|
|
646
|
+
_validate_chitchat_dependencies(pattern_chitchat, model_configuration)
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def _validate_chitchat_dependencies(
|
|
650
|
+
pattern_chitchat: Flow, model_configuration: GraphModelConfiguration
|
|
651
|
+
) -> None:
|
|
652
|
+
"""Validate that the IntentlessPolicy is configured if the pattern_chitchat
|
|
653
|
+
is using action_trigger_chitchat.
|
|
654
|
+
"""
|
|
655
|
+
has_action_trigger_chitchat = pattern_chitchat.has_action_step(
|
|
656
|
+
ACTION_TRIGGER_CHITCHAT
|
|
657
|
+
)
|
|
658
|
+
has_intentless_policy_configured = model_configuration.predict_schema.has_node(
|
|
659
|
+
IntentlessPolicy
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
if has_action_trigger_chitchat and not has_intentless_policy_configured:
|
|
663
|
+
structlogger.warn(
|
|
664
|
+
f"flow_component_dependencies"
|
|
665
|
+
f".{FLOW_PATTERN_CHITCHAT}"
|
|
666
|
+
f".intentless_policy_not_configured",
|
|
667
|
+
event_info=(
|
|
668
|
+
f"`{FLOW_PATTERN_CHITCHAT}` has an action step with "
|
|
669
|
+
f"`{ACTION_TRIGGER_CHITCHAT}`, but `IntentlessPolicy` is not "
|
|
670
|
+
f"configured."
|
|
671
|
+
),
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
|
|
676
|
+
"""Extracts the index of a component of the given class in the schema.
|
|
677
|
+
This function assumes that each component's node name is stored in a way
|
|
678
|
+
that includes the index as part of the name, formatted as
|
|
679
|
+
"run_{ComponentName}{Index}", which is how it's created by the recipe.
|
|
680
|
+
"""
|
|
681
|
+
# the index of the component is at the end of the node name
|
|
682
|
+
pattern = re.compile(r"\d+$")
|
|
683
|
+
for node_name, node in schema.nodes.items():
|
|
684
|
+
if issubclass(node.uses, component_class):
|
|
685
|
+
match = pattern.search(node_name)
|
|
686
|
+
if match:
|
|
687
|
+
index = int(match.group())
|
|
688
|
+
return index
|
|
689
|
+
# index is not found or there is no component with the given class
|
|
690
|
+
return None
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def get_component_config(
|
|
694
|
+
schema: GraphSchema, component_class: Type
|
|
695
|
+
) -> Optional[Dict[str, Any]]:
|
|
696
|
+
"""Extracts the config of a component of the given class in the schema."""
|
|
697
|
+
for node_name, node in schema.nodes.items():
|
|
698
|
+
if issubclass(node.uses, component_class):
|
|
699
|
+
return node.config
|
|
700
|
+
return None
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
def validate_router_exclusivity(schema: GraphSchema) -> None:
|
|
704
|
+
"""Validate that intent-based and llm-based routers are not
|
|
705
|
+
defined at the same time.
|
|
706
|
+
"""
|
|
707
|
+
if schema.has_node(IntentBasedRouter) and schema.has_node(LLMBasedRouter):
|
|
708
|
+
structlogger.error(
|
|
709
|
+
"validation.coexistance.both_routers_defined",
|
|
710
|
+
event_info=(
|
|
711
|
+
"Both LLMBasedRouter and IntentBasedRouter are in the config. "
|
|
712
|
+
"Please use only one of them."
|
|
713
|
+
),
|
|
714
|
+
)
|
|
715
|
+
sys.exit(1)
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
def validate_intent_based_router_position(schema: GraphSchema) -> None:
|
|
719
|
+
"""Validate that if intent-based router is defined, it is positioned before
|
|
720
|
+
the llm command generator.
|
|
721
|
+
"""
|
|
722
|
+
intent_based_router_pos = get_component_index(schema, IntentBasedRouter)
|
|
723
|
+
llm_command_generator_pos = get_component_index(schema, LLMBasedCommandGenerator)
|
|
724
|
+
if (
|
|
725
|
+
intent_based_router_pos is not None
|
|
726
|
+
and llm_command_generator_pos is not None
|
|
727
|
+
and intent_based_router_pos > llm_command_generator_pos
|
|
728
|
+
):
|
|
729
|
+
structlogger.error(
|
|
730
|
+
"validation.coexistance.wrong_order_of_components",
|
|
731
|
+
event_info=(
|
|
732
|
+
"IntentBasedRouter should come before "
|
|
733
|
+
"a LLMBasedCommandGenerator in the pipeline."
|
|
734
|
+
),
|
|
735
|
+
)
|
|
736
|
+
sys.exit(1)
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
def validate_that_slots_are_defined_if_router_is_defined(
|
|
740
|
+
schema: GraphSchema, routing_slots: List[Slot]
|
|
741
|
+
) -> None:
|
|
742
|
+
# check whether intent-based or llm-based type of router is present
|
|
743
|
+
for router_type in [IntentBasedRouter, LLMBasedRouter]:
|
|
744
|
+
router_present = schema.has_node(router_type)
|
|
745
|
+
slot_has_issue = len(routing_slots) == 0 or routing_slots[0].type_name != "bool"
|
|
746
|
+
if router_present and slot_has_issue:
|
|
747
|
+
structlogger.error(
|
|
748
|
+
f"validation.coexistance.{ROUTE_TO_CALM_SLOT}_not_in_domain",
|
|
749
|
+
event_info=(
|
|
750
|
+
f"{router_type.__name__} is in the config, but the slot "
|
|
751
|
+
f"{ROUTE_TO_CALM_SLOT} is not in the domain or not of "
|
|
752
|
+
f"type bool."
|
|
753
|
+
),
|
|
754
|
+
)
|
|
755
|
+
sys.exit(1)
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
def validate_that_router_is_defined_if_router_slots_are_in_domain(
|
|
759
|
+
schema: GraphSchema,
|
|
760
|
+
routing_slots: List[Slot],
|
|
761
|
+
) -> None:
|
|
762
|
+
defined_router_slots = len(routing_slots) > 0
|
|
763
|
+
router_present = schema.has_node(IntentBasedRouter) or schema.has_node(
|
|
764
|
+
LLMBasedRouter
|
|
765
|
+
)
|
|
766
|
+
if defined_router_slots and (
|
|
767
|
+
not router_present or routing_slots[0].type_name != "bool"
|
|
768
|
+
):
|
|
769
|
+
structlogger.error(
|
|
770
|
+
f"validation.coexistance"
|
|
771
|
+
f".{ROUTE_TO_CALM_SLOT}_in_domain_with_no_router_defined",
|
|
772
|
+
event_info=(
|
|
773
|
+
f"The slot {ROUTE_TO_CALM_SLOT} is in the domain but the "
|
|
774
|
+
f"LLMBasedRouter or the IntentBasedRouter is not in the config or "
|
|
775
|
+
f"the type of the slot is not bool."
|
|
776
|
+
),
|
|
777
|
+
)
|
|
778
|
+
sys.exit(1)
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
def valid_nlu_entry_config(config: Optional[Dict[str, Any]]) -> bool:
|
|
782
|
+
return (
|
|
783
|
+
config is not None
|
|
784
|
+
and NLU_ENTRY in config
|
|
785
|
+
and isinstance(config[NLU_ENTRY], dict)
|
|
786
|
+
and STICKY in config[NLU_ENTRY]
|
|
787
|
+
and NON_STICKY in config[NLU_ENTRY]
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
def valid_calm_entry_config(config: Optional[Dict[str, Any]]) -> bool:
|
|
792
|
+
return (
|
|
793
|
+
config is not None
|
|
794
|
+
and CALM_ENTRY in config
|
|
795
|
+
and isinstance(config[CALM_ENTRY], dict)
|
|
796
|
+
and STICKY in config[CALM_ENTRY]
|
|
797
|
+
)
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
def validate_configuration(
|
|
801
|
+
schema: GraphSchema,
|
|
802
|
+
) -> None:
|
|
803
|
+
"""Validate the configuration of the existing coexistence routers."""
|
|
804
|
+
if schema.has_node(IntentBasedRouter, include_subtypes=False):
|
|
805
|
+
config = get_component_config(schema, IntentBasedRouter)
|
|
806
|
+
if not valid_calm_entry_config(config) or not valid_nlu_entry_config(config):
|
|
807
|
+
structlogger.error(
|
|
808
|
+
"validation.coexistance.invalid_configuration",
|
|
809
|
+
event_info=(
|
|
810
|
+
"The configuration of the IntentBasedRouter is invalid. "
|
|
811
|
+
"Please check the documentation.",
|
|
812
|
+
),
|
|
813
|
+
)
|
|
814
|
+
sys.exit(1)
|
|
815
|
+
|
|
816
|
+
if schema.has_node(LLMBasedRouter, include_subtypes=False):
|
|
817
|
+
config = get_component_config(schema, LLMBasedRouter)
|
|
818
|
+
if not valid_calm_entry_config(config) or (
|
|
819
|
+
config is not None
|
|
820
|
+
and NLU_ENTRY in config
|
|
821
|
+
and not valid_nlu_entry_config(config)
|
|
822
|
+
):
|
|
823
|
+
structlogger.error(
|
|
824
|
+
"validation.coexistance.invalid_configuration",
|
|
825
|
+
event_info=(
|
|
826
|
+
"The configuration of the LLMBasedRouter is invalid. "
|
|
827
|
+
"Please check the documentation.",
|
|
828
|
+
),
|
|
829
|
+
)
|
|
830
|
+
sys.exit(1)
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
def validate_coexistance_routing_setup(
|
|
834
|
+
domain: Domain, model_configuration: GraphModelConfiguration, flows: FlowsList
|
|
835
|
+
) -> None:
|
|
836
|
+
schema = model_configuration.predict_schema
|
|
837
|
+
routing_slots = [s for s in domain.slots if s.name == ROUTE_TO_CALM_SLOT]
|
|
838
|
+
|
|
839
|
+
def validate_that_router_or_router_slot_are_defined_if_action_reset_routing_is_used(
|
|
840
|
+
schema: GraphSchema, flows: FlowsList, routing_slots: List[Slot]
|
|
841
|
+
) -> None:
|
|
842
|
+
slot_has_issue = len(routing_slots) == 0 or routing_slots[0].type_name != "bool"
|
|
843
|
+
router_present = schema.has_node(LLMBasedRouter) or schema.has_node(
|
|
844
|
+
IntentBasedRouter
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
if router_present or not slot_has_issue:
|
|
848
|
+
return
|
|
849
|
+
|
|
850
|
+
faulty_flows_with_action_reset_routing = [
|
|
851
|
+
flow for flow in flows if flow.has_action_step(ACTION_RESET_ROUTING)
|
|
852
|
+
]
|
|
853
|
+
|
|
854
|
+
if faulty_flows_with_action_reset_routing:
|
|
855
|
+
for flow in faulty_flows_with_action_reset_routing:
|
|
856
|
+
structlogger.error(
|
|
857
|
+
f"validation.coexistance.{ACTION_RESET_ROUTING}_present_in_flow"
|
|
858
|
+
f"_without_router_or_{ROUTE_TO_CALM_SLOT}_slot",
|
|
859
|
+
event_info=(
|
|
860
|
+
f"The action - {ACTION_RESET_ROUTING} is used in the flow - "
|
|
861
|
+
f"{flow.id}, but a router (LLMBasedRouter/IntentBasedRouter) or"
|
|
862
|
+
f" {ROUTE_TO_CALM_SLOT} are not defined.",
|
|
863
|
+
),
|
|
864
|
+
)
|
|
865
|
+
sys.exit(1)
|
|
866
|
+
|
|
867
|
+
validate_router_exclusivity(schema)
|
|
868
|
+
validate_intent_based_router_position(schema)
|
|
869
|
+
validate_that_slots_are_defined_if_router_is_defined(schema, routing_slots)
|
|
870
|
+
validate_that_router_is_defined_if_router_slots_are_in_domain(schema, routing_slots)
|
|
871
|
+
validate_configuration(schema)
|
|
872
|
+
validate_that_router_or_router_slot_are_defined_if_action_reset_routing_is_used(
|
|
873
|
+
schema, flows, routing_slots
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
def _validate_component_model_client_config(
|
|
878
|
+
component_config: Dict[str, Any],
|
|
879
|
+
key: str,
|
|
880
|
+
model_group_syntax_used: List[bool],
|
|
881
|
+
model_group_ids: List[str],
|
|
882
|
+
component_name: Optional[str] = None,
|
|
883
|
+
) -> None:
|
|
884
|
+
"""Validate the LLM configuration of a component.
|
|
885
|
+
|
|
886
|
+
Checks if the llm is defined using the new syntax or the old syntax.
|
|
887
|
+
If the new syntax is used, it checks that no other parameters are present.
|
|
888
|
+
|
|
889
|
+
Args:
|
|
890
|
+
component_config: The config of the component
|
|
891
|
+
key: either 'llm' or 'embeddings'
|
|
892
|
+
model_group_syntax_used:
|
|
893
|
+
list of booleans indicating whether the new syntax is used
|
|
894
|
+
model_group_ids: list of model group ids
|
|
895
|
+
component_name: the name of the component
|
|
896
|
+
"""
|
|
897
|
+
if key not in component_config:
|
|
898
|
+
# no llm configuration present
|
|
899
|
+
return
|
|
900
|
+
|
|
901
|
+
if MODEL_GROUP_CONFIG_KEY in component_config[key]:
|
|
902
|
+
model_group_syntax_used.append(True)
|
|
903
|
+
model_group_ids.append(component_config[key][MODEL_GROUP_CONFIG_KEY])
|
|
904
|
+
|
|
905
|
+
if len(component_config[key]) > 1:
|
|
906
|
+
structlogger.error(
|
|
907
|
+
"validation.validate_model_client_configuration_setup"
|
|
908
|
+
".only_model_group_reference_key_is_allowed",
|
|
909
|
+
event_info=(
|
|
910
|
+
f"You specified a '{MODEL_GROUP_CONFIG_KEY}' for the '{key}' "
|
|
911
|
+
f"config key for the component "
|
|
912
|
+
f"'{component_name or component_config['name']}'. "
|
|
913
|
+
"No other parameters are allowed under the "
|
|
914
|
+
f"'{key}' key in that case. Please update your config."
|
|
915
|
+
),
|
|
916
|
+
component_name=component_name or component_config["name"],
|
|
917
|
+
component_client_config_key=key,
|
|
918
|
+
)
|
|
919
|
+
sys.exit(1)
|
|
920
|
+
else:
|
|
921
|
+
model_group_syntax_used.append(False)
|
|
922
|
+
|
|
923
|
+
# check that any of the sensitive data keys is not set in config
|
|
924
|
+
for secret_key in SENSITIVE_DATA:
|
|
925
|
+
if secret_key in component_config[key]:
|
|
926
|
+
structlogger.error(
|
|
927
|
+
"validation.validate_model_client_configuration_setup"
|
|
928
|
+
".secret_key_not_allowed_in_the_config",
|
|
929
|
+
event_info=(
|
|
930
|
+
f"You specified '{secret_key}' in the config for "
|
|
931
|
+
f"'{component_name or component_config['name']}', "
|
|
932
|
+
f"which is not allowed. "
|
|
933
|
+
"Set secret keys through environment variables."
|
|
934
|
+
),
|
|
935
|
+
component_name=component_name or component_config["name"],
|
|
936
|
+
component_client_config_key=key,
|
|
937
|
+
secret_key=secret_key,
|
|
938
|
+
)
|
|
939
|
+
sys.exit(1)
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
def validate_model_client_configuration_setup_during_training_time(
|
|
943
|
+
config: Dict[str, Any],
|
|
944
|
+
) -> None:
|
|
945
|
+
"""Validates the model client configuration setup.
|
|
946
|
+
|
|
947
|
+
Checks the model configuration of the components in the pipeline.
|
|
948
|
+
Validation fails, if
|
|
949
|
+
- the LLM/embeddings is/are defined using the old and the new syntax at
|
|
950
|
+
the same time (either at component level itself or across different components)
|
|
951
|
+
- the LLM/embeddings is/are defined using the new syntax, but no model
|
|
952
|
+
group is defined or the referenced model group does not exist
|
|
953
|
+
- the LLM/embeddings provider is defined using 'api_type' key for providers other
|
|
954
|
+
than 'openai' or 'azure'
|
|
955
|
+
|
|
956
|
+
Args:
|
|
957
|
+
config: The config dictionary
|
|
958
|
+
"""
|
|
959
|
+
|
|
960
|
+
def is_uniform_bool_list(bool_list: List[bool]) -> bool:
|
|
961
|
+
# check if list contains only True or False
|
|
962
|
+
return all(bool_list) or not any(bool_list)
|
|
963
|
+
|
|
964
|
+
model_group_syntax_used: List[bool] = []
|
|
965
|
+
model_group_ids: List[str] = []
|
|
966
|
+
|
|
967
|
+
for outer_key in ["pipeline", "policies"]:
|
|
968
|
+
if outer_key not in config or config[outer_key] is None:
|
|
969
|
+
continue
|
|
970
|
+
|
|
971
|
+
for component_config in config[outer_key]:
|
|
972
|
+
for key in [LLM_CONFIG_KEY, EMBEDDINGS_CONFIG_KEY]:
|
|
973
|
+
_validate_component_model_client_config(
|
|
974
|
+
component_config, key, model_group_syntax_used, model_group_ids
|
|
975
|
+
)
|
|
976
|
+
validate_api_type_config_key_usage(component_config, key)
|
|
977
|
+
|
|
978
|
+
# as flow retrieval is not a component itself, we need to
|
|
979
|
+
# check it separately
|
|
980
|
+
if FLOW_RETRIEVAL_KEY in component_config:
|
|
981
|
+
if EMBEDDINGS_CONFIG_KEY in component_config[FLOW_RETRIEVAL_KEY]:
|
|
982
|
+
_validate_component_model_client_config(
|
|
983
|
+
component_config[FLOW_RETRIEVAL_KEY],
|
|
984
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
985
|
+
model_group_syntax_used,
|
|
986
|
+
model_group_ids,
|
|
987
|
+
component_config["name"] + "." + FLOW_RETRIEVAL_KEY,
|
|
988
|
+
)
|
|
989
|
+
validate_api_type_config_key_usage(
|
|
990
|
+
component_config[FLOW_RETRIEVAL_KEY],
|
|
991
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
992
|
+
component_config["name"] + "." + FLOW_RETRIEVAL_KEY,
|
|
993
|
+
)
|
|
994
|
+
|
|
995
|
+
# also include the ContextualResponseRephraser component
|
|
996
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
997
|
+
if endpoints.nlg is not None:
|
|
998
|
+
_validate_component_model_client_config(
|
|
999
|
+
endpoints.nlg.kwargs,
|
|
1000
|
+
LLM_CONFIG_KEY,
|
|
1001
|
+
model_group_syntax_used,
|
|
1002
|
+
model_group_ids,
|
|
1003
|
+
ContextualResponseRephraser.__name__,
|
|
1004
|
+
)
|
|
1005
|
+
|
|
1006
|
+
if not is_uniform_bool_list(model_group_syntax_used):
|
|
1007
|
+
structlogger.error(
|
|
1008
|
+
"validation.validate_model_client_configuration_setup"
|
|
1009
|
+
".inconsistent_use_of_model_group_syntax",
|
|
1010
|
+
event_info=(
|
|
1011
|
+
"Some of your components refer to an LLM using the "
|
|
1012
|
+
f"'{MODEL_GROUP_CONFIG_KEY}' parameter, other components directly"
|
|
1013
|
+
f" define the LLM under the '{LLM_CONFIG_KEY}' or the "
|
|
1014
|
+
f"'{EMBEDDINGS_CONFIG_KEY}' key. You cannot use"
|
|
1015
|
+
" both types of definitions. Please chose one syntax "
|
|
1016
|
+
"and update your config."
|
|
1017
|
+
),
|
|
1018
|
+
)
|
|
1019
|
+
sys.exit(1)
|
|
1020
|
+
|
|
1021
|
+
# Print a deprecation warning in case the old syntax is used.
|
|
1022
|
+
if len(model_group_syntax_used) > 0 and model_group_syntax_used[0] is False:
|
|
1023
|
+
structlogger.warning(
|
|
1024
|
+
"validate_llm_configuration_setup",
|
|
1025
|
+
event_info=(
|
|
1026
|
+
"Defining the LLM configuration in the config.yml file itself is"
|
|
1027
|
+
" deprecated and will be removed in Rasa 4.0.0. "
|
|
1028
|
+
"Please use the new syntax and define your LLM configuration"
|
|
1029
|
+
"in the endpoints.yml file."
|
|
1030
|
+
),
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
1034
|
+
if len(model_group_ids) > 0 and endpoints.model_groups is None:
|
|
1035
|
+
structlogger.error(
|
|
1036
|
+
"validation.validate_model_client_configuration_setup"
|
|
1037
|
+
".referencing_model_group_but_none_are_defined",
|
|
1038
|
+
event_info=(
|
|
1039
|
+
"You are referring to (a) model group(s) in your "
|
|
1040
|
+
"config.yml file, but no model group was defined in "
|
|
1041
|
+
"the endpoints.yml file. Please define the model "
|
|
1042
|
+
"group(s)."
|
|
1043
|
+
),
|
|
1044
|
+
)
|
|
1045
|
+
sys.exit(1)
|
|
1046
|
+
|
|
1047
|
+
if endpoints.model_groups is None:
|
|
1048
|
+
return
|
|
1049
|
+
|
|
1050
|
+
existing_model_group_ids = [
|
|
1051
|
+
model_group[MODEL_GROUP_ID_CONFIG_KEY] for model_group in endpoints.model_groups
|
|
1052
|
+
]
|
|
1053
|
+
|
|
1054
|
+
for model_group_id in model_group_ids:
|
|
1055
|
+
if model_group_id not in existing_model_group_ids:
|
|
1056
|
+
structlogger.error(
|
|
1057
|
+
"validation.validate_model_client_configuration_setup"
|
|
1058
|
+
".referencing_undefined_model_group",
|
|
1059
|
+
event_info=(
|
|
1060
|
+
"One of your components is referring to the model group "
|
|
1061
|
+
f"'{model_group_id}', but this model group does not exist in the "
|
|
1062
|
+
f"endpoints.yml file. Please chose one of the existing "
|
|
1063
|
+
f"model groups ({existing_model_group_ids}) or define "
|
|
1064
|
+
f"the model group for '{model_group_id}'."
|
|
1065
|
+
),
|
|
1066
|
+
referencing_model_group_id=model_group_id,
|
|
1067
|
+
existing_model_group_ids=existing_model_group_ids,
|
|
1068
|
+
)
|
|
1069
|
+
sys.exit(1)
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
def _validate_component_model_client_config_has_references_to_endpoints(
|
|
1073
|
+
component_config: Dict[Text, Any],
|
|
1074
|
+
key: str,
|
|
1075
|
+
component_name: Optional[Text] = None,
|
|
1076
|
+
) -> None:
|
|
1077
|
+
"""Validates that the specified client configuration references a valid model group
|
|
1078
|
+
defined in the `endpoints.yml` file.
|
|
1079
|
+
|
|
1080
|
+
This function ensures that when the client configuration for a component uses the
|
|
1081
|
+
`model_group` key, the referenced model group exists in the `endpoints.yml` file.
|
|
1082
|
+
If the referenced model group is missing or invalid, an error is raised.
|
|
1083
|
+
|
|
1084
|
+
Args:
|
|
1085
|
+
component_config: The configuration dictionary for the component being
|
|
1086
|
+
validated.
|
|
1087
|
+
key: 'llm' or 'embeddings'
|
|
1088
|
+
component_name: Optional; the name of the component being validated, used for
|
|
1089
|
+
error messages.
|
|
1090
|
+
|
|
1091
|
+
Raises:
|
|
1092
|
+
SystemExit: If the referenced model group is missing or invalid.
|
|
1093
|
+
"""
|
|
1094
|
+
if key not in component_config:
|
|
1095
|
+
# no llm/embeddings configuration present
|
|
1096
|
+
return
|
|
1097
|
+
|
|
1098
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
1099
|
+
|
|
1100
|
+
if MODEL_GROUP_CONFIG_KEY in component_config[key]:
|
|
1101
|
+
referencing_model_group_id = component_config[key][MODEL_GROUP_CONFIG_KEY]
|
|
1102
|
+
|
|
1103
|
+
if endpoints.model_groups is None:
|
|
1104
|
+
structlogger.error(
|
|
1105
|
+
"validation.validate_model_client_config_correctly_references_endpoints"
|
|
1106
|
+
".no_model_groups_defined",
|
|
1107
|
+
event_info=(
|
|
1108
|
+
f"Your {component_name or component_config.get('name') or ''} "
|
|
1109
|
+
f"component's '{key}' configuration of the trained model "
|
|
1110
|
+
f"references the model group '{referencing_model_group_id}', "
|
|
1111
|
+
f"but NO MODEL GROUPS ARE DEFINED in the endpoints.yml file. "
|
|
1112
|
+
f"Please add a definition for the required model group in the "
|
|
1113
|
+
f"endpoints.yml file."
|
|
1114
|
+
),
|
|
1115
|
+
component_name=component_name or component_config.get("name"),
|
|
1116
|
+
model_group_id=referencing_model_group_id,
|
|
1117
|
+
component_client_config_key=key,
|
|
1118
|
+
)
|
|
1119
|
+
sys.exit(1)
|
|
1120
|
+
|
|
1121
|
+
existing_model_group_ids = [
|
|
1122
|
+
model_group[MODEL_GROUP_ID_CONFIG_KEY]
|
|
1123
|
+
for model_group in endpoints.model_groups
|
|
1124
|
+
]
|
|
1125
|
+
|
|
1126
|
+
if referencing_model_group_id not in existing_model_group_ids:
|
|
1127
|
+
structlogger.error(
|
|
1128
|
+
"validation.validate_model_client_config_correctly_references_endpoints"
|
|
1129
|
+
".referenced_model_group_does_not_exist",
|
|
1130
|
+
event_info=(
|
|
1131
|
+
f"Your {component_name or component_config.get('name') or ''} "
|
|
1132
|
+
f"component's '{key}' configuration of the trained model "
|
|
1133
|
+
f"references the model group '{referencing_model_group_id}', "
|
|
1134
|
+
f"but this model group DOES NOT EXIST in the endpoints.yml file. "
|
|
1135
|
+
f"The endpoints.yml defines the following model groups: "
|
|
1136
|
+
f"{existing_model_group_ids}. "
|
|
1137
|
+
f"Please add a definition for the required model group in the "
|
|
1138
|
+
f"endpoints.yml file."
|
|
1139
|
+
),
|
|
1140
|
+
model_group_id=referencing_model_group_id,
|
|
1141
|
+
existing_model_group_ids=existing_model_group_ids,
|
|
1142
|
+
component_client_config_key=key,
|
|
1143
|
+
)
|
|
1144
|
+
sys.exit(1)
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
def validate_model_client_configuration_setup_during_inference_time(
|
|
1148
|
+
model_metadata: ModelMetadata,
|
|
1149
|
+
) -> None:
|
|
1150
|
+
for (
|
|
1151
|
+
component_node_name,
|
|
1152
|
+
component_node,
|
|
1153
|
+
) in model_metadata.predict_schema.nodes.items():
|
|
1154
|
+
for client_config_key in [EMBEDDINGS_CONFIG_KEY, LLM_CONFIG_KEY]:
|
|
1155
|
+
if client_config_key not in component_node.config:
|
|
1156
|
+
continue
|
|
1157
|
+
|
|
1158
|
+
_validate_component_model_client_config_has_references_to_endpoints(
|
|
1159
|
+
component_config=component_node.config,
|
|
1160
|
+
key=client_config_key,
|
|
1161
|
+
component_name=component_node_name,
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
# as flow retrieval is not a component itself, we need to
|
|
1165
|
+
# check it separately
|
|
1166
|
+
if FLOW_RETRIEVAL_KEY in component_node.config:
|
|
1167
|
+
if EMBEDDINGS_CONFIG_KEY in component_node.config[FLOW_RETRIEVAL_KEY]:
|
|
1168
|
+
_validate_component_model_client_config_has_references_to_endpoints(
|
|
1169
|
+
component_config=component_node.config[FLOW_RETRIEVAL_KEY],
|
|
1170
|
+
key=EMBEDDINGS_CONFIG_KEY,
|
|
1171
|
+
component_name=component_node_name + "." + FLOW_RETRIEVAL_KEY,
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
# also include the ContextualResponseRephraser component
|
|
1175
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
1176
|
+
if endpoints.nlg is not None:
|
|
1177
|
+
_validate_component_model_client_config_has_references_to_endpoints(
|
|
1178
|
+
component_config=endpoints.nlg.kwargs,
|
|
1179
|
+
key=LLM_CONFIG_KEY,
|
|
1180
|
+
component_name=ContextualResponseRephraser.__name__,
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
def _validate_unique_model_group_ids(model_groups: List[Dict[str, Any]]) -> None:
|
|
1185
|
+
# Each model id must be unique within the model_groups
|
|
1186
|
+
model_ids = [model_group[MODEL_GROUP_ID_CONFIG_KEY] for model_group in model_groups]
|
|
1187
|
+
if len(model_ids) != len(set(model_ids)):
|
|
1188
|
+
structlogger.error(
|
|
1189
|
+
"validate_model_group_configuration_setup.non_unique_model_group_ids",
|
|
1190
|
+
event_info=(
|
|
1191
|
+
"Each model group id must be unique. Please make sure that "
|
|
1192
|
+
"the model group ids are unique in your endpoints.yml file."
|
|
1193
|
+
),
|
|
1194
|
+
)
|
|
1195
|
+
sys.exit(1)
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
def _validate_model_group_with_multiple_models(
|
|
1199
|
+
model_groups: List[Dict[str, Any]],
|
|
1200
|
+
) -> None:
|
|
1201
|
+
# You cannot define multiple models within a model group, when no router is defined.
|
|
1202
|
+
for model_group in model_groups:
|
|
1203
|
+
if (
|
|
1204
|
+
len(model_group[MODELS_CONFIG_KEY]) > 1
|
|
1205
|
+
and ROUTER_CONFIG_KEY not in model_group
|
|
1206
|
+
):
|
|
1207
|
+
structlogger.error(
|
|
1208
|
+
"validate_model_group_configuration_setup.router_not_present",
|
|
1209
|
+
event_info=(
|
|
1210
|
+
f"You defined multiple models for the model group "
|
|
1211
|
+
f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}', but no router. "
|
|
1212
|
+
"If a model group contains multiple models, a router must be "
|
|
1213
|
+
"defined. Please define a router for the model group "
|
|
1214
|
+
f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}'."
|
|
1215
|
+
),
|
|
1216
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1217
|
+
)
|
|
1218
|
+
sys.exit(1)
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
def _validate_model_group_router_setting(
|
|
1222
|
+
model_groups: List[Dict[str, Any]],
|
|
1223
|
+
) -> None:
|
|
1224
|
+
# You cannot define multiple models within a model group, when no router is defined.
|
|
1225
|
+
for model_group in model_groups:
|
|
1226
|
+
if ROUTER_CONFIG_KEY not in model_group:
|
|
1227
|
+
continue
|
|
1228
|
+
|
|
1229
|
+
for model_config in model_group.get(MODELS_CONFIG_KEY, []):
|
|
1230
|
+
if USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY in model_config:
|
|
1231
|
+
structlogger.error(
|
|
1232
|
+
"validation.validate_model_group_configuration_setup"
|
|
1233
|
+
f".{USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY}_set_incorrectly",
|
|
1234
|
+
event_info=(
|
|
1235
|
+
f"You defined the '{USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY}' "
|
|
1236
|
+
f"in the model group "
|
|
1237
|
+
f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}'. This key is not "
|
|
1238
|
+
f"allowed in the model configuration as the router is defined. "
|
|
1239
|
+
f"Please remove this key from your model configuration and "
|
|
1240
|
+
f"update it in the '{ROUTER_CONFIG_KEY} configuration, as it "
|
|
1241
|
+
f"is a router level setting."
|
|
1242
|
+
),
|
|
1243
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1244
|
+
)
|
|
1245
|
+
sys.exit(1)
|
|
1246
|
+
|
|
1247
|
+
router_config = model_group[ROUTER_CONFIG_KEY]
|
|
1248
|
+
if ROUTING_STRATEGY_CONFIG_KEY in router_config:
|
|
1249
|
+
routing_strategy = router_config.get(ROUTING_STRATEGY_CONFIG_KEY)
|
|
1250
|
+
if routing_strategy and routing_strategy not in VALID_ROUTING_STRATEGIES:
|
|
1251
|
+
structlogger.error(
|
|
1252
|
+
"validation.validate_model_group_configuration_setup"
|
|
1253
|
+
".invalid_routing_strategy",
|
|
1254
|
+
event_info=(
|
|
1255
|
+
f"The routing strategy '{routing_strategy}' you defined for "
|
|
1256
|
+
f"the model group '{model_group[MODEL_GROUP_ID_CONFIG_KEY]}' "
|
|
1257
|
+
f"is not valid. Valid routing strategies are categorized as "
|
|
1258
|
+
f"follows:\n"
|
|
1259
|
+
f"- Strategies requiring Redis caching: "
|
|
1260
|
+
f"{', '.join(ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE)}\n"
|
|
1261
|
+
f"- Strategies not requiring caching: "
|
|
1262
|
+
f"{', '.join(ROUTING_STRATEGIES_NOT_REQUIRING_CACHE)}"
|
|
1263
|
+
),
|
|
1264
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1265
|
+
invalid_routing_strategy=routing_strategy,
|
|
1266
|
+
supported_routing_strategies_requiring_redis_cache=(
|
|
1267
|
+
ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE
|
|
1268
|
+
),
|
|
1269
|
+
supported_routing_strategies_not_requiring_redis_cache=(
|
|
1270
|
+
ROUTING_STRATEGIES_NOT_REQUIRING_CACHE
|
|
1271
|
+
),
|
|
1272
|
+
)
|
|
1273
|
+
sys.exit(1)
|
|
1274
|
+
if (
|
|
1275
|
+
routing_strategy in ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE
|
|
1276
|
+
and REDIS_HOST_CONFIG_KEY not in router_config
|
|
1277
|
+
):
|
|
1278
|
+
structlogger.warning(
|
|
1279
|
+
"validation.routing_strategy.redis_host_not_defined",
|
|
1280
|
+
event_info=(
|
|
1281
|
+
f"The routing strategy '{routing_strategy}' requires a Redis "
|
|
1282
|
+
f"host to be defined. Without a Redis host, the system "
|
|
1283
|
+
f"defaults to 'in-memory' caching. Please add the "
|
|
1284
|
+
f"'{REDIS_HOST_CONFIG_KEY}' to the router configuration for "
|
|
1285
|
+
f"the model group '{model_group[MODEL_GROUP_ID_CONFIG_KEY]}'."
|
|
1286
|
+
),
|
|
1287
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1288
|
+
)
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
def _validate_usage_of_environment_variables_in_model_group_config(
|
|
1292
|
+
model_groups: List[Dict[str, Any]],
|
|
1293
|
+
) -> None:
|
|
1294
|
+
# Limit the use of ${env_var} in the model_groups config to the following variables:
|
|
1295
|
+
# - deployment,
|
|
1296
|
+
# - api_base, api_version and api_key,
|
|
1297
|
+
# - aws_region_name, aws_access_key_id, aws_secret_access_key, and aws_session_token
|
|
1298
|
+
allowed_env_vars = {
|
|
1299
|
+
DEPLOYMENT_CONFIG_KEY,
|
|
1300
|
+
API_BASE_CONFIG_KEY,
|
|
1301
|
+
API_KEY,
|
|
1302
|
+
API_VERSION_CONFIG_KEY,
|
|
1303
|
+
AWS_REGION_NAME_CONFIG_KEY,
|
|
1304
|
+
AWS_ACCESS_KEY_ID_CONFIG_KEY,
|
|
1305
|
+
AWS_SECRET_ACCESS_KEY_CONFIG_KEY,
|
|
1306
|
+
AWS_SESSION_TOKEN_CONFIG_KEY,
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
for model_group in model_groups:
|
|
1310
|
+
for model_config in model_group[MODELS_CONFIG_KEY]:
|
|
1311
|
+
for key, value in model_config.items():
|
|
1312
|
+
if isinstance(value, str):
|
|
1313
|
+
if re.match(r"\${(\w+)}", value) and key not in allowed_env_vars:
|
|
1314
|
+
structlogger.error(
|
|
1315
|
+
"validation.validate_model_group_configuration_setup"
|
|
1316
|
+
".invalid_use_of_environment_variables",
|
|
1317
|
+
event_info=(
|
|
1318
|
+
f"You defined '{key}' as environment variable in model "
|
|
1319
|
+
f"group '{model_group[MODEL_GROUP_ID_CONFIG_KEY]}', "
|
|
1320
|
+
f"which is not allowed. "
|
|
1321
|
+
f"You can only use environment variables for the "
|
|
1322
|
+
f"following keys: {', '.join(allowed_env_vars)}. "
|
|
1323
|
+
f"Please update your config."
|
|
1324
|
+
),
|
|
1325
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1326
|
+
key=key,
|
|
1327
|
+
allowed_keys_for_env_vars=allowed_env_vars,
|
|
1328
|
+
)
|
|
1329
|
+
sys.exit(1)
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
|
|
1333
|
+
model_groups: List[Dict[str, Any]],
|
|
1334
|
+
) -> None:
|
|
1335
|
+
# the api key can only be set as an environment variable
|
|
1336
|
+
for model_group in model_groups:
|
|
1337
|
+
for model_config in model_group[MODELS_CONFIG_KEY]:
|
|
1338
|
+
for key, value in model_config.items():
|
|
1339
|
+
if key in SENSITIVE_DATA:
|
|
1340
|
+
if isinstance(value, str):
|
|
1341
|
+
if not re.match(r"\${(\w+)}", value):
|
|
1342
|
+
structlogger.error(
|
|
1343
|
+
"validation.validate_model_group_configuration_setup"
|
|
1344
|
+
".sensitive_key_string_value_must_be_set_as_env_var",
|
|
1345
|
+
event_info=(
|
|
1346
|
+
f"You defined the '{key}' in model group "
|
|
1347
|
+
f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}' as a "
|
|
1348
|
+
f"string. The '{key}' must be set as an "
|
|
1349
|
+
f"environment variable. Please update your config."
|
|
1350
|
+
),
|
|
1351
|
+
key=key,
|
|
1352
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1353
|
+
)
|
|
1354
|
+
sys.exit(1)
|
|
1355
|
+
else:
|
|
1356
|
+
structlogger.error(
|
|
1357
|
+
"validation.validate_model_group_configuration_setup"
|
|
1358
|
+
".sensitive_key_must_be_set_as_env_var",
|
|
1359
|
+
event_info=(
|
|
1360
|
+
f"You should define the '{key}' in model group "
|
|
1361
|
+
f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}' using the "
|
|
1362
|
+
f"environment variable syntax - "
|
|
1363
|
+
f"${{ENV_VARIABLE_NAME}}. "
|
|
1364
|
+
f"Please update your config."
|
|
1365
|
+
),
|
|
1366
|
+
key=key,
|
|
1367
|
+
model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
|
|
1368
|
+
)
|
|
1369
|
+
sys.exit(1)
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
def validate_model_group_configuration_setup() -> None:
|
|
1373
|
+
"""Validates the model group configuration setup in endpoints.yml."""
|
|
1374
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
1375
|
+
|
|
1376
|
+
if endpoints.model_groups is None:
|
|
1377
|
+
return
|
|
1378
|
+
|
|
1379
|
+
_validate_unique_model_group_ids(endpoints.model_groups)
|
|
1380
|
+
_validate_model_group_with_multiple_models(endpoints.model_groups)
|
|
1381
|
+
_validate_usage_of_environment_variables_in_model_group_config(
|
|
1382
|
+
endpoints.model_groups
|
|
1383
|
+
)
|
|
1384
|
+
_validate_sensitive_keys_are_an_environment_variables_for_model_groups(
|
|
1385
|
+
endpoints.model_groups
|
|
1386
|
+
)
|
|
1387
|
+
_validate_model_group_router_setting(endpoints.model_groups)
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
def validate_command_generator_exclusivity(schema: GraphSchema) -> None:
|
|
1391
|
+
"""Validate that multiple command generators are not defined at same time."""
|
|
1392
|
+
from rasa.dialogue_understanding.generator import (
|
|
1393
|
+
LLMBasedCommandGenerator,
|
|
1394
|
+
)
|
|
1395
|
+
|
|
1396
|
+
count = schema.count_nodes_of_a_given_type(
|
|
1397
|
+
LLMBasedCommandGenerator, include_subtypes=True
|
|
1398
|
+
)
|
|
1399
|
+
|
|
1400
|
+
if count > 1:
|
|
1401
|
+
structlogger.error(
|
|
1402
|
+
"validation.command_generator.multiple_command_generator_defined",
|
|
1403
|
+
event_info=(
|
|
1404
|
+
"Multiple LLM based command generators are defined in the config. "
|
|
1405
|
+
"Please use only one LLM based command generator."
|
|
1406
|
+
),
|
|
1407
|
+
)
|
|
1408
|
+
sys.exit(1)
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
def validate_command_generator_setup(
|
|
1412
|
+
model_configuration: GraphModelConfiguration,
|
|
1413
|
+
) -> None:
|
|
1414
|
+
schema = model_configuration.predict_schema
|
|
1415
|
+
validate_command_generator_exclusivity(schema)
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
def validate_api_type_config_key_usage(
|
|
1419
|
+
component_config: Dict[str, Any],
|
|
1420
|
+
key: Literal["llm", "embeddings"],
|
|
1421
|
+
component_name: Optional[str] = None,
|
|
1422
|
+
) -> None:
|
|
1423
|
+
"""Validate the LLM/embeddings configuration of a component.
|
|
1424
|
+
|
|
1425
|
+
Validation fails, if
|
|
1426
|
+
- the LLM/embeddings provider is defined using 'api_type' key for providers other
|
|
1427
|
+
than 'openai' or 'azure'
|
|
1428
|
+
|
|
1429
|
+
Args:
|
|
1430
|
+
component_config: The config of the component
|
|
1431
|
+
key: either 'llm' or 'embeddings'
|
|
1432
|
+
component_name: the name of the component
|
|
1433
|
+
"""
|
|
1434
|
+
if component_config is None or key not in component_config:
|
|
1435
|
+
return
|
|
1436
|
+
|
|
1437
|
+
if API_TYPE_CONFIG_KEY in component_config[key]:
|
|
1438
|
+
api_type = component_config[key][API_TYPE_CONFIG_KEY]
|
|
1439
|
+
if api_type not in VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY:
|
|
1440
|
+
structlogger.error(
|
|
1441
|
+
"validation.component.api_type_config_key_invalid",
|
|
1442
|
+
event_info=(
|
|
1443
|
+
f"You specified '{API_TYPE_CONFIG_KEY}: {api_type}' for "
|
|
1444
|
+
f"'{component_name or component_config['name']}', which is not "
|
|
1445
|
+
f"allowed. "
|
|
1446
|
+
f"The '{API_TYPE_CONFIG_KEY}' key can only be used for the "
|
|
1447
|
+
f"following providers: {VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY}. "
|
|
1448
|
+
f"For other providers, please use the '{PROVIDER_CONFIG_KEY}' key."
|
|
1449
|
+
),
|
|
1450
|
+
)
|
|
1451
|
+
sys.exit(1)
|