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,1031 @@
|
|
|
1
|
+
import importlib.resources
|
|
2
|
+
import math
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Text, Tuple
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
import tiktoken
|
|
8
|
+
from jinja2 import Template
|
|
9
|
+
from langchain.docstore.document import Document
|
|
10
|
+
from langchain.schema.embeddings import Embeddings
|
|
11
|
+
from langchain_community.vectorstores.faiss import FAISS
|
|
12
|
+
|
|
13
|
+
import rasa.shared.utils.io
|
|
14
|
+
from rasa import telemetry
|
|
15
|
+
from rasa.core.constants import (
|
|
16
|
+
CHAT_POLICY_PRIORITY,
|
|
17
|
+
POLICY_PRIORITY,
|
|
18
|
+
UTTER_SOURCE_METADATA_KEY,
|
|
19
|
+
)
|
|
20
|
+
from rasa.core.policies.policy import Policy, PolicyPrediction, SupportedData
|
|
21
|
+
from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
22
|
+
from rasa.dialogue_understanding.stack.frames import (
|
|
23
|
+
ChitChatStackFrame,
|
|
24
|
+
DialogueStackFrame,
|
|
25
|
+
)
|
|
26
|
+
from rasa.engine.graph import ExecutionContext
|
|
27
|
+
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
|
|
28
|
+
from rasa.engine.storage.resource import Resource
|
|
29
|
+
from rasa.engine.storage.storage import ModelStorage
|
|
30
|
+
from rasa.graph_components.providers.forms_provider import Forms
|
|
31
|
+
from rasa.graph_components.providers.responses_provider import Responses
|
|
32
|
+
from rasa.shared.constants import (
|
|
33
|
+
REQUIRED_SLOTS_KEY,
|
|
34
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
35
|
+
LLM_CONFIG_KEY,
|
|
36
|
+
MODEL_CONFIG_KEY,
|
|
37
|
+
MODEL_NAME_CONFIG_KEY,
|
|
38
|
+
PROMPT_CONFIG_KEY,
|
|
39
|
+
PROVIDER_CONFIG_KEY,
|
|
40
|
+
OPENAI_PROVIDER,
|
|
41
|
+
TIMEOUT_CONFIG_KEY,
|
|
42
|
+
MODEL_GROUP_ID_CONFIG_KEY,
|
|
43
|
+
)
|
|
44
|
+
from rasa.shared.core.constants import ACTION_LISTEN_NAME
|
|
45
|
+
from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT
|
|
46
|
+
from rasa.shared.core.domain import KEY_RESPONSES_TEXT, Domain
|
|
47
|
+
from rasa.shared.core.events import (
|
|
48
|
+
ActionExecuted,
|
|
49
|
+
BotUttered,
|
|
50
|
+
Event,
|
|
51
|
+
UserUttered,
|
|
52
|
+
)
|
|
53
|
+
from rasa.shared.core.flows import FlowsList
|
|
54
|
+
from rasa.shared.core.generator import TrackerWithCachedStates
|
|
55
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
56
|
+
from rasa.shared.exceptions import FileIOException, RasaCoreException
|
|
57
|
+
from rasa.shared.nlu.constants import PREDICTED_CONFIDENCE_KEY
|
|
58
|
+
from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
59
|
+
from rasa.shared.providers.embedding._langchain_embedding_client_adapter import (
|
|
60
|
+
_LangchainEmbeddingClientAdapter,
|
|
61
|
+
)
|
|
62
|
+
from rasa.shared.providers.llm.llm_client import LLMClient
|
|
63
|
+
from rasa.shared.utils.health_check.embeddings_health_check_mixin import (
|
|
64
|
+
EmbeddingsHealthCheckMixin,
|
|
65
|
+
)
|
|
66
|
+
from rasa.shared.utils.health_check.llm_health_check_mixin import LLMHealthCheckMixin
|
|
67
|
+
from rasa.shared.utils.io import deep_container_fingerprint
|
|
68
|
+
from rasa.shared.utils.llm import (
|
|
69
|
+
AI,
|
|
70
|
+
DEFAULT_OPENAI_CHAT_MODEL_NAME,
|
|
71
|
+
DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
|
|
72
|
+
DEFAULT_OPENAI_MAX_GENERATED_TOKENS,
|
|
73
|
+
USER,
|
|
74
|
+
combine_custom_and_default_config,
|
|
75
|
+
embedder_factory,
|
|
76
|
+
get_prompt_template,
|
|
77
|
+
llm_factory,
|
|
78
|
+
sanitize_message_for_prompt,
|
|
79
|
+
tracker_as_readable_transcript,
|
|
80
|
+
resolve_model_client_config,
|
|
81
|
+
)
|
|
82
|
+
from rasa.utils.log_utils import log_llm
|
|
83
|
+
from rasa.utils.ml_utils import (
|
|
84
|
+
extract_ai_response_examples,
|
|
85
|
+
extract_participant_messages_from_transcript,
|
|
86
|
+
form_utterances_to_action,
|
|
87
|
+
load_faiss_vector_store,
|
|
88
|
+
persist_faiss_vector_store,
|
|
89
|
+
response_for_template,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if TYPE_CHECKING:
|
|
93
|
+
from rasa.core.featurizers.tracker_featurizers import TrackerFeaturizer
|
|
94
|
+
|
|
95
|
+
structlogger = structlog.get_logger()
|
|
96
|
+
|
|
97
|
+
NUMBER_OF_CONVERSATION_SAMPLES = 5
|
|
98
|
+
|
|
99
|
+
NUMBER_OF_RESPONSE_SAMPLES = 20
|
|
100
|
+
|
|
101
|
+
# GPT-3 model's MAX_TOKEN = 2049
|
|
102
|
+
# https://platform.openai.com/docs/models/gpt-3
|
|
103
|
+
# get_response_prompt empty template uses around 149 tokens
|
|
104
|
+
# equal number of tokens for conversation and responses
|
|
105
|
+
# (2049 - 149) / 2 = 950
|
|
106
|
+
# 100 tokens for input
|
|
107
|
+
MAX_NUMBER_OF_TOKENS_FOR_SAMPLES = 900
|
|
108
|
+
|
|
109
|
+
# the config property name for the confidence of the nlu prediction
|
|
110
|
+
NLU_ABSTENTION_THRESHOLD = "nlu_abstention_threshold"
|
|
111
|
+
|
|
112
|
+
DEFAULT_LLM_CONFIG = {
|
|
113
|
+
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
114
|
+
MODEL_CONFIG_KEY: DEFAULT_OPENAI_CHAT_MODEL_NAME,
|
|
115
|
+
"temperature": 0.0,
|
|
116
|
+
"max_tokens": DEFAULT_OPENAI_MAX_GENERATED_TOKENS,
|
|
117
|
+
TIMEOUT_CONFIG_KEY: 5,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
DEFAULT_EMBEDDINGS_CONFIG = {
|
|
121
|
+
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
122
|
+
"model": DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
DEFAULT_INTENTLESS_PROMPT_TEMPLATE = importlib.resources.open_text(
|
|
126
|
+
"rasa.core.policies", "intentless_prompt_template.jinja2"
|
|
127
|
+
).name
|
|
128
|
+
|
|
129
|
+
INTENTLESS_PROMPT_TEMPLATE_FILE_NAME = "intentless_policy_prompt.jinja2"
|
|
130
|
+
INTENTLESS_CONFIG_FILE_NAME = "config.json"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class RasaMLPolicyTrainingException(RasaCoreException):
|
|
134
|
+
"""Raised when training fails."""
|
|
135
|
+
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class Interaction:
|
|
141
|
+
text: str
|
|
142
|
+
actor: str
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass
|
|
146
|
+
class Conversation:
|
|
147
|
+
interactions: List[Interaction] = field(default_factory=list)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def collect_form_responses(forms: Forms) -> Set[Text]:
|
|
151
|
+
"""Collect responses that belong the requested slots in forms.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
forms: the forms from the domain
|
|
155
|
+
Returns:
|
|
156
|
+
all utterances used in forms
|
|
157
|
+
"""
|
|
158
|
+
form_responses = set()
|
|
159
|
+
for _, form_info in forms.data.items():
|
|
160
|
+
for required_slot in form_info.get(REQUIRED_SLOTS_KEY, []):
|
|
161
|
+
form_responses.add(f"utter_ask_{required_slot}")
|
|
162
|
+
return form_responses
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def filter_responses(responses: Responses, forms: Forms, flows: FlowsList) -> Responses:
|
|
166
|
+
"""Filters out responses that are unwanted for the intentless policy.
|
|
167
|
+
|
|
168
|
+
This includes utterances used in flows and forms.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
responses: the responses from the domain
|
|
172
|
+
forms: the forms from the domain
|
|
173
|
+
flows: all flows
|
|
174
|
+
Returns:
|
|
175
|
+
The remaining, relevant responses for the intentless policy.
|
|
176
|
+
"""
|
|
177
|
+
form_responses = collect_form_responses(forms)
|
|
178
|
+
flow_responses = flows.utterances
|
|
179
|
+
combined_responses = form_responses | flow_responses
|
|
180
|
+
filtered_responses = {
|
|
181
|
+
name: variants
|
|
182
|
+
for name, variants in responses.data.items()
|
|
183
|
+
if name not in combined_responses
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
pattern_chitchat = flows.flow_by_id(FLOW_PATTERN_CHITCHAT)
|
|
187
|
+
|
|
188
|
+
# The following condition is highly unlikely, but mypy requires the case
|
|
189
|
+
# of pattern_chitchat == None to be addressed
|
|
190
|
+
if not pattern_chitchat:
|
|
191
|
+
return Responses(data=filtered_responses)
|
|
192
|
+
|
|
193
|
+
# if action_trigger_chitchat, filter out "utter_free_chitchat_response"
|
|
194
|
+
has_action_trigger_chitchat = pattern_chitchat.has_action_step(
|
|
195
|
+
ACTION_TRIGGER_CHITCHAT
|
|
196
|
+
)
|
|
197
|
+
if has_action_trigger_chitchat:
|
|
198
|
+
filtered_responses.pop("utter_free_chitchat_response", None)
|
|
199
|
+
|
|
200
|
+
return Responses(data=filtered_responses)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def action_from_response(
|
|
204
|
+
text: Optional[str], responses: Dict[Text, List[Dict[Text, Any]]]
|
|
205
|
+
) -> Optional[str]:
|
|
206
|
+
"""Returns the action associated with the given response text.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
text: The response text.
|
|
210
|
+
responses: The responses from the domain.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
The action associated with the response text, or None if no action is found.
|
|
214
|
+
"""
|
|
215
|
+
if not text:
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
for action, variations in responses.items():
|
|
219
|
+
for variation in variations:
|
|
220
|
+
if variation.get(KEY_RESPONSES_TEXT) == text:
|
|
221
|
+
return action
|
|
222
|
+
return None
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _conversation_sample_from_tracker(
|
|
226
|
+
tracker: DialogueStateTracker,
|
|
227
|
+
responses: Dict[Text, List[Dict[Text, Any]]],
|
|
228
|
+
) -> Optional[Conversation]:
|
|
229
|
+
"""Extracts a conversation sample from the given tracker.
|
|
230
|
+
|
|
231
|
+
Example:
|
|
232
|
+
>>> tracker = DialogueStateTracker(
|
|
233
|
+
... "default",
|
|
234
|
+
... slots=[],
|
|
235
|
+
... active_loop={},
|
|
236
|
+
... events=[
|
|
237
|
+
... UserUttered("hello"),
|
|
238
|
+
... BotUttered("hey there!"),
|
|
239
|
+
... UserUttered("goodbye"),
|
|
240
|
+
... BotUttered("bye bye!"),
|
|
241
|
+
... ],
|
|
242
|
+
... )
|
|
243
|
+
>>> _conversation_sample_from_tracker(tracker)
|
|
244
|
+
Conversation(interactions=[
|
|
245
|
+
Interaction(actor='user', text='hello'),
|
|
246
|
+
Interaction(actor='bot', text='hey there!'),
|
|
247
|
+
Interaction(actor='user', text='goodbye'),
|
|
248
|
+
Interaction(actor='bot', text='bye bye!'),
|
|
249
|
+
])
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
tracker: The tracker to extract a conversation sample from.
|
|
253
|
+
responses: The responses from the domain.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
The conversation sample, or None if the tracker doesn't contain a
|
|
257
|
+
conversation sample.
|
|
258
|
+
"""
|
|
259
|
+
conversation = Conversation()
|
|
260
|
+
for event in tracker.applied_events():
|
|
261
|
+
if isinstance(event, UserUttered):
|
|
262
|
+
if event.text is None:
|
|
263
|
+
# need to abort here, as we can't use this conversation
|
|
264
|
+
# sample as it doesn't have an actual user message attached
|
|
265
|
+
# likely, this is just an intent.
|
|
266
|
+
return None
|
|
267
|
+
conversation.interactions.append(Interaction(actor=USER, text=event.text))
|
|
268
|
+
elif isinstance(event, BotUttered):
|
|
269
|
+
conversation.interactions.append(
|
|
270
|
+
Interaction(actor=AI, text=event.text or "")
|
|
271
|
+
)
|
|
272
|
+
elif (
|
|
273
|
+
isinstance(event, ActionExecuted)
|
|
274
|
+
and event.action_name
|
|
275
|
+
and event.action_name.startswith("utter_")
|
|
276
|
+
):
|
|
277
|
+
response = response_for_template(event.action_name, responses)
|
|
278
|
+
if response:
|
|
279
|
+
interaction = Interaction(actor=AI, text=response)
|
|
280
|
+
conversation.interactions.append(interaction)
|
|
281
|
+
else:
|
|
282
|
+
# need to abort here, as we can't use this conversation
|
|
283
|
+
# sample as it doesn't have a response for the utterance
|
|
284
|
+
# that was used in the story.
|
|
285
|
+
return None
|
|
286
|
+
# Do not use reduced conversations with just one or no utterances
|
|
287
|
+
if len(conversation.interactions) < 2:
|
|
288
|
+
structlogger.debug(
|
|
289
|
+
"intentless_policy.sampled_conversation.skipped",
|
|
290
|
+
interations=conversation.interactions,
|
|
291
|
+
)
|
|
292
|
+
return None
|
|
293
|
+
# Do not use conversation with only user or only bot
|
|
294
|
+
if len({m.actor for m in conversation.interactions}) < 2:
|
|
295
|
+
structlogger.debug(
|
|
296
|
+
"intentless_policy.sampled_conversation.skipped",
|
|
297
|
+
interactions=conversation.interactions,
|
|
298
|
+
)
|
|
299
|
+
return None
|
|
300
|
+
return conversation
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def conversation_samples_from_trackers(
|
|
304
|
+
training_trackers: List[TrackerWithCachedStates],
|
|
305
|
+
responses: Dict[Text, List[Dict[Text, Any]]],
|
|
306
|
+
) -> List[Conversation]:
|
|
307
|
+
"""Extracts conversation samples from the given trackers.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
training_trackers: The trackers to extract conversation samples from.
|
|
311
|
+
responses: The responses from the domain.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
The conversation samples.
|
|
315
|
+
"""
|
|
316
|
+
return [
|
|
317
|
+
sample
|
|
318
|
+
for tracker in training_trackers
|
|
319
|
+
if (sample := _conversation_sample_from_tracker(tracker, responses))
|
|
320
|
+
]
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def truncate_documents(
|
|
324
|
+
docs: List[Document],
|
|
325
|
+
max_number_of_tokens: int,
|
|
326
|
+
model_name: str = DEFAULT_OPENAI_CHAT_MODEL_NAME,
|
|
327
|
+
) -> List[Document]:
|
|
328
|
+
"""Takes first n documents that contains less then `max_number_of_tokens` tokens.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
docs: Sequence of documents that needs to be truncated.
|
|
332
|
+
max_number_of_tokens: Maximum number of tokens to preserve.
|
|
333
|
+
model_name: Name of the model to use for tokenization.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
Sequence of documents that contains less then `max_number_of_tokens` tokens.
|
|
337
|
+
"""
|
|
338
|
+
enc = tiktoken.encoding_for_model(model_name)
|
|
339
|
+
|
|
340
|
+
truncated_docs = []
|
|
341
|
+
docs_token_num = 0
|
|
342
|
+
for doc in docs:
|
|
343
|
+
doc_token_num = len(enc.encode(doc.page_content))
|
|
344
|
+
if docs_token_num + doc_token_num > max_number_of_tokens:
|
|
345
|
+
break
|
|
346
|
+
|
|
347
|
+
docs_token_num += doc_token_num
|
|
348
|
+
truncated_docs.append(doc)
|
|
349
|
+
|
|
350
|
+
return truncated_docs
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def conversation_as_prompt(conversation: Conversation) -> str:
|
|
354
|
+
"""Converts the given conversation to a prompt.
|
|
355
|
+
|
|
356
|
+
Example:
|
|
357
|
+
>>> conversation = Conversation(interactions=[
|
|
358
|
+
... Interaction(actor=USER, text="hi"),
|
|
359
|
+
... Interaction(actor=AI, text="Hello World!")
|
|
360
|
+
... ])
|
|
361
|
+
>>> print(conversation_as_prompt(conversation))
|
|
362
|
+
USER: hi
|
|
363
|
+
AI: Hello World!
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
conversation: The conversation to convert.
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
The prompt.
|
|
370
|
+
"""
|
|
371
|
+
return "\n".join(
|
|
372
|
+
f"{m.actor}: {sanitize_message_for_prompt(m.text)}"
|
|
373
|
+
for m in conversation.interactions
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@DefaultV1Recipe.register(
|
|
378
|
+
DefaultV1Recipe.ComponentType.POLICY_WITH_END_TO_END_SUPPORT, is_trainable=True
|
|
379
|
+
)
|
|
380
|
+
class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
|
|
381
|
+
"""Policy which uses a language model to generate the next action.
|
|
382
|
+
|
|
383
|
+
The policy uses the OpenAI API to generate the next action based on the
|
|
384
|
+
conversation history. The policy can be used to generate a response for
|
|
385
|
+
the user or to predict the next action.
|
|
386
|
+
"""
|
|
387
|
+
|
|
388
|
+
@staticmethod
|
|
389
|
+
def get_default_config() -> Dict[Text, Any]:
|
|
390
|
+
"""Returns the default config (see parent class for full docstring)."""
|
|
391
|
+
# please make sure to update the docs when changing a default parameter
|
|
392
|
+
return {
|
|
393
|
+
POLICY_PRIORITY: CHAT_POLICY_PRIORITY,
|
|
394
|
+
# the abstention threshold is used to determine whether the policy
|
|
395
|
+
# should predict an action or abstain from prediction. if the
|
|
396
|
+
# nlu predictions confidence is above the threshold, the
|
|
397
|
+
# policy will predict with a score lower than the threshold. this
|
|
398
|
+
# ensures that the policy will not override a deterministic policy
|
|
399
|
+
# which utilizes the nlu predictions confidence (e.g. Memoization).
|
|
400
|
+
NLU_ABSTENTION_THRESHOLD: 0.9,
|
|
401
|
+
LLM_CONFIG_KEY: DEFAULT_LLM_CONFIG,
|
|
402
|
+
EMBEDDINGS_CONFIG_KEY: DEFAULT_EMBEDDINGS_CONFIG,
|
|
403
|
+
PROMPT_CONFIG_KEY: DEFAULT_INTENTLESS_PROMPT_TEMPLATE,
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
@staticmethod
|
|
407
|
+
def supported_data() -> SupportedData:
|
|
408
|
+
"""The type of data supported by this policy.
|
|
409
|
+
|
|
410
|
+
By default, this is only ML-based training data. If policies support rule data,
|
|
411
|
+
or both ML-based data and rule data, they need to override this method.
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
The data type supported by this policy (ML-based training data).
|
|
415
|
+
"""
|
|
416
|
+
return SupportedData.ML_DATA
|
|
417
|
+
|
|
418
|
+
@staticmethod
|
|
419
|
+
def does_support_stack_frame(frame: DialogueStackFrame) -> bool:
|
|
420
|
+
"""Checks if the policy supports the given stack frame."""
|
|
421
|
+
return isinstance(frame, ChitChatStackFrame)
|
|
422
|
+
|
|
423
|
+
def __init__(
|
|
424
|
+
self,
|
|
425
|
+
config: Dict[Text, Any],
|
|
426
|
+
model_storage: ModelStorage,
|
|
427
|
+
resource: Resource,
|
|
428
|
+
execution_context: ExecutionContext,
|
|
429
|
+
featurizer: Optional["TrackerFeaturizer"] = None,
|
|
430
|
+
responses_docsearch: Optional["FAISS"] = None,
|
|
431
|
+
samples_docsearch: Optional["FAISS"] = None,
|
|
432
|
+
prompt_template: Optional[Text] = None,
|
|
433
|
+
) -> None:
|
|
434
|
+
"""Constructs a new Policy object."""
|
|
435
|
+
super().__init__(config, model_storage, resource, execution_context, featurizer)
|
|
436
|
+
|
|
437
|
+
# Resolve LLM config
|
|
438
|
+
self.config[LLM_CONFIG_KEY] = resolve_model_client_config(
|
|
439
|
+
self.config.get(LLM_CONFIG_KEY), IntentlessPolicy.__name__
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# Resolve embeddings config
|
|
443
|
+
self.config[EMBEDDINGS_CONFIG_KEY] = resolve_model_client_config(
|
|
444
|
+
self.config.get(EMBEDDINGS_CONFIG_KEY), IntentlessPolicy.__name__
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
self.nlu_abstention_threshold: float = self.config[NLU_ABSTENTION_THRESHOLD]
|
|
448
|
+
self.response_index = responses_docsearch
|
|
449
|
+
self.conversation_samples_index = samples_docsearch
|
|
450
|
+
self.embedder = self._create_plain_embedder(config)
|
|
451
|
+
self.prompt_template = prompt_template or rasa.shared.utils.io.read_file(
|
|
452
|
+
self.config[PROMPT_CONFIG_KEY]
|
|
453
|
+
)
|
|
454
|
+
self.trace_prompt_tokens = self.config.get("trace_prompt_tokens", False)
|
|
455
|
+
|
|
456
|
+
@classmethod
|
|
457
|
+
def _create_plain_embedder(cls, config: Dict[Text, Any]) -> Embeddings:
|
|
458
|
+
"""Creates an embedder that uses the OpenAI API.
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
The embedder.
|
|
462
|
+
"""
|
|
463
|
+
# Copy the config so original config is not modified
|
|
464
|
+
config.copy()
|
|
465
|
+
# Resolve config and instantiate the embedding client
|
|
466
|
+
config[EMBEDDINGS_CONFIG_KEY] = resolve_model_client_config(
|
|
467
|
+
config.get(EMBEDDINGS_CONFIG_KEY), IntentlessPolicy.__name__
|
|
468
|
+
)
|
|
469
|
+
client = embedder_factory(
|
|
470
|
+
config.get(EMBEDDINGS_CONFIG_KEY), DEFAULT_EMBEDDINGS_CONFIG
|
|
471
|
+
)
|
|
472
|
+
# Wrap the embedding client in the adapter
|
|
473
|
+
return _LangchainEmbeddingClientAdapter(client)
|
|
474
|
+
|
|
475
|
+
def embeddings_property(self, prop: str) -> Optional[str]:
|
|
476
|
+
"""Returns the property of the embeddings config."""
|
|
477
|
+
return combine_custom_and_default_config(
|
|
478
|
+
self.config.get(EMBEDDINGS_CONFIG_KEY), DEFAULT_EMBEDDINGS_CONFIG
|
|
479
|
+
).get(prop)
|
|
480
|
+
|
|
481
|
+
def llm_property(self, prop: str) -> Optional[str]:
|
|
482
|
+
"""Returns the property of the LLM config."""
|
|
483
|
+
return combine_custom_and_default_config(
|
|
484
|
+
self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG
|
|
485
|
+
).get(prop)
|
|
486
|
+
|
|
487
|
+
def train( # type: ignore[override]
|
|
488
|
+
self,
|
|
489
|
+
training_trackers: List[TrackerWithCachedStates],
|
|
490
|
+
domain: Domain,
|
|
491
|
+
responses: Responses,
|
|
492
|
+
forms: Forms,
|
|
493
|
+
training_data: TrainingData,
|
|
494
|
+
flows: Optional[FlowsList],
|
|
495
|
+
**kwargs: Any,
|
|
496
|
+
) -> Resource:
|
|
497
|
+
"""Trains a policy.
|
|
498
|
+
|
|
499
|
+
Args:
|
|
500
|
+
training_trackers: The story and rules trackers from the training data.
|
|
501
|
+
domain: The model's domain.
|
|
502
|
+
responses: The model's responses.
|
|
503
|
+
forms: The model's forms.
|
|
504
|
+
training_data: The model's training data.
|
|
505
|
+
flows: all existing flows for task-oriented processes
|
|
506
|
+
**kwargs: Depending on the specified `needs` section and the resulting
|
|
507
|
+
graph structure the policy can use different input to train itself.
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
A policy must return its resource locator so that potential children nodes
|
|
511
|
+
can load the policy from the resource.
|
|
512
|
+
"""
|
|
513
|
+
# Perform health checks of both LLM and embeddings client configs
|
|
514
|
+
self._perform_health_checks(self.config, "intentless_policy.train")
|
|
515
|
+
|
|
516
|
+
responses = filter_responses(responses, forms, flows or FlowsList([]))
|
|
517
|
+
telemetry.track_intentless_policy_train()
|
|
518
|
+
response_texts = [r for r in extract_ai_response_examples(responses.data)]
|
|
519
|
+
|
|
520
|
+
selected_trackers = [
|
|
521
|
+
t for t in training_trackers if not t.is_augmented and not t.is_rule_tracker
|
|
522
|
+
]
|
|
523
|
+
|
|
524
|
+
conversation_samples = conversation_samples_from_trackers(
|
|
525
|
+
selected_trackers, responses.data
|
|
526
|
+
)
|
|
527
|
+
conversations = [
|
|
528
|
+
prompt
|
|
529
|
+
for c in conversation_samples
|
|
530
|
+
if (prompt := conversation_as_prompt(c))
|
|
531
|
+
]
|
|
532
|
+
|
|
533
|
+
try:
|
|
534
|
+
self.response_index = (
|
|
535
|
+
FAISS.from_texts(response_texts, self.embedder, normalize_L2=True)
|
|
536
|
+
if response_texts
|
|
537
|
+
else None
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
self.conversation_samples_index = (
|
|
541
|
+
FAISS.from_texts(conversations, self.embedder)
|
|
542
|
+
if conversations
|
|
543
|
+
else None
|
|
544
|
+
)
|
|
545
|
+
except Exception as e:
|
|
546
|
+
structlogger.error(
|
|
547
|
+
"intentless_policy.train.llm.error",
|
|
548
|
+
error=e,
|
|
549
|
+
)
|
|
550
|
+
raise RasaMLPolicyTrainingException(
|
|
551
|
+
"The training of the Intentless Policy failed due to an error "
|
|
552
|
+
"with the LLM provider. Sorry about that! "
|
|
553
|
+
"You can retry your request."
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
structlogger.info("intentless_policy.training.completed")
|
|
557
|
+
telemetry.track_intentless_policy_train_completed(
|
|
558
|
+
embeddings_type=self.embeddings_property(PROVIDER_CONFIG_KEY),
|
|
559
|
+
embeddings_model=self.embeddings_property(MODEL_CONFIG_KEY)
|
|
560
|
+
or self.embeddings_property(MODEL_NAME_CONFIG_KEY),
|
|
561
|
+
embeddings_model_group_id=self.embeddings_property(
|
|
562
|
+
MODEL_GROUP_ID_CONFIG_KEY
|
|
563
|
+
),
|
|
564
|
+
llm_type=self.llm_property(PROVIDER_CONFIG_KEY),
|
|
565
|
+
llm_model=self.llm_property(MODEL_CONFIG_KEY)
|
|
566
|
+
or self.llm_property(MODEL_NAME_CONFIG_KEY),
|
|
567
|
+
llm_model_group_id=self.llm_property(MODEL_GROUP_ID_CONFIG_KEY),
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
self.persist()
|
|
571
|
+
return self._resource
|
|
572
|
+
|
|
573
|
+
def persist(self) -> None:
|
|
574
|
+
"""Persists the policy to storage."""
|
|
575
|
+
with self._model_storage.write_to(self._resource) as path:
|
|
576
|
+
persist_faiss_vector_store(path / "responses_faiss", self.response_index)
|
|
577
|
+
persist_faiss_vector_store(
|
|
578
|
+
path / "samples_faiss", self.conversation_samples_index
|
|
579
|
+
)
|
|
580
|
+
rasa.shared.utils.io.write_text_file(
|
|
581
|
+
self.prompt_template, path / INTENTLESS_PROMPT_TEMPLATE_FILE_NAME
|
|
582
|
+
)
|
|
583
|
+
rasa.shared.utils.io.dump_obj_as_json_to_file(
|
|
584
|
+
path / INTENTLESS_CONFIG_FILE_NAME, self.config
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
async def predict_action_probabilities(
|
|
588
|
+
self,
|
|
589
|
+
tracker: DialogueStateTracker,
|
|
590
|
+
domain: Domain,
|
|
591
|
+
rule_only_data: Optional[Dict[Text, Any]] = None,
|
|
592
|
+
**kwargs: Any,
|
|
593
|
+
) -> PolicyPrediction:
|
|
594
|
+
"""Predicts the next action the bot should take after seeing the tracker.
|
|
595
|
+
|
|
596
|
+
Args:
|
|
597
|
+
tracker: The tracker containing the conversation history up to now.
|
|
598
|
+
domain: The model's domain.
|
|
599
|
+
rule_only_data: Slots and loops which are specific to rules and hence
|
|
600
|
+
should be ignored by this policy.
|
|
601
|
+
**kwargs: Depending on the specified `needs` section and the resulting
|
|
602
|
+
graph structure the policy can use different input to make predictions.
|
|
603
|
+
|
|
604
|
+
Returns:
|
|
605
|
+
The prediction.
|
|
606
|
+
"""
|
|
607
|
+
if not self.supports_current_stack_frame(
|
|
608
|
+
tracker
|
|
609
|
+
) or self.should_abstain_in_coexistence(tracker, True):
|
|
610
|
+
return self._prediction(self._default_predictions(domain))
|
|
611
|
+
|
|
612
|
+
if tracker.has_bot_message_after_latest_user_message():
|
|
613
|
+
# if the last event was a bot utterance, we either want to
|
|
614
|
+
# return to the active loop or else predict action_listen as
|
|
615
|
+
# this is the end of the turn
|
|
616
|
+
if tracker.active_loop_name:
|
|
617
|
+
result = self._prediction_result(tracker.active_loop_name, domain)
|
|
618
|
+
else:
|
|
619
|
+
result = self._prediction_result(ACTION_LISTEN_NAME, domain)
|
|
620
|
+
return self._prediction(result)
|
|
621
|
+
|
|
622
|
+
if not self.response_index:
|
|
623
|
+
# we don't have any responses, so we can't predict anything
|
|
624
|
+
result = self._default_predictions(domain)
|
|
625
|
+
return self._prediction(result)
|
|
626
|
+
|
|
627
|
+
response, score = await self.find_closest_response(tracker)
|
|
628
|
+
|
|
629
|
+
predicted_action_name = action_from_response(response, domain.responses)
|
|
630
|
+
|
|
631
|
+
form_utterances = form_utterances_to_action(domain)
|
|
632
|
+
if predicted_action_name in form_utterances:
|
|
633
|
+
# if the predicted action is a form utterance, we need to predict the form
|
|
634
|
+
# action instead
|
|
635
|
+
predicted_action_name = form_utterances[predicted_action_name]
|
|
636
|
+
|
|
637
|
+
structlogger.info(
|
|
638
|
+
"intentless_policy.prediction.completed",
|
|
639
|
+
predicted_action_name=predicted_action_name,
|
|
640
|
+
score=score,
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
telemetry.track_intentless_policy_predict(
|
|
644
|
+
embeddings_type=self.embeddings_property(PROVIDER_CONFIG_KEY),
|
|
645
|
+
embeddings_model=self.embeddings_property(MODEL_CONFIG_KEY)
|
|
646
|
+
or self.embeddings_property(MODEL_NAME_CONFIG_KEY),
|
|
647
|
+
embeddings_model_group_id=self.embeddings_property(
|
|
648
|
+
MODEL_GROUP_ID_CONFIG_KEY
|
|
649
|
+
),
|
|
650
|
+
llm_type=self.llm_property(PROVIDER_CONFIG_KEY),
|
|
651
|
+
llm_model=self.llm_property(MODEL_CONFIG_KEY)
|
|
652
|
+
or self.llm_property(MODEL_NAME_CONFIG_KEY),
|
|
653
|
+
llm_model_group_id=self.llm_property(MODEL_GROUP_ID_CONFIG_KEY),
|
|
654
|
+
score=score,
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
result = self._prediction_result(predicted_action_name, domain, score)
|
|
658
|
+
|
|
659
|
+
stack = tracker.stack
|
|
660
|
+
if not stack.is_empty():
|
|
661
|
+
stack.pop()
|
|
662
|
+
events: List[Event] = tracker.create_stack_updated_events(stack)
|
|
663
|
+
else:
|
|
664
|
+
events = []
|
|
665
|
+
|
|
666
|
+
action_metadata = {UTTER_SOURCE_METADATA_KEY: self.__class__.__name__}
|
|
667
|
+
|
|
668
|
+
return self._prediction(result, events=events, action_metadata=action_metadata)
|
|
669
|
+
|
|
670
|
+
async def generate_answer(
|
|
671
|
+
self,
|
|
672
|
+
response_examples: List[str],
|
|
673
|
+
conversation_samples: List[str],
|
|
674
|
+
history: str,
|
|
675
|
+
) -> Optional[str]:
|
|
676
|
+
"""Make the llm call to generate an answer."""
|
|
677
|
+
llm = llm_factory(self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG)
|
|
678
|
+
inputs = {
|
|
679
|
+
"conversations": conversation_samples,
|
|
680
|
+
"responses": response_examples,
|
|
681
|
+
"current_conversation": history,
|
|
682
|
+
}
|
|
683
|
+
prompt = Template(self.prompt_template).render(**inputs)
|
|
684
|
+
log_llm(
|
|
685
|
+
logger=structlogger,
|
|
686
|
+
log_module="IntentlessPolicy",
|
|
687
|
+
log_event="intentless_policy.generate_answer.prompt_rendered",
|
|
688
|
+
prompt=prompt,
|
|
689
|
+
)
|
|
690
|
+
return await self._generate_llm_answer(llm, prompt)
|
|
691
|
+
|
|
692
|
+
async def _generate_llm_answer(self, llm: LLMClient, prompt: str) -> Optional[str]:
|
|
693
|
+
try:
|
|
694
|
+
llm_response = await llm.acompletion(prompt)
|
|
695
|
+
return llm_response.choices[0]
|
|
696
|
+
except Exception as e:
|
|
697
|
+
# unfortunately, langchain does not wrap LLM exceptions which means
|
|
698
|
+
# we have to catch all exceptions here
|
|
699
|
+
structlogger.error("intentless_policy.answer_generation.failed", error=e)
|
|
700
|
+
return None
|
|
701
|
+
|
|
702
|
+
def embed_llm_response(self, llm_response: str) -> Optional[List[float]]:
|
|
703
|
+
"""Embed the llm response."""
|
|
704
|
+
try:
|
|
705
|
+
# using embed documents here because the responses are the documents
|
|
706
|
+
return self.embedder.embed_documents([llm_response])[0]
|
|
707
|
+
except Exception as e:
|
|
708
|
+
# unfortunately, langchain does not wrap LLM exceptions which means
|
|
709
|
+
# we have to catch all exceptions here
|
|
710
|
+
structlogger.error("intentless_policy.answer_embedding.failed", error=e)
|
|
711
|
+
return None
|
|
712
|
+
|
|
713
|
+
async def find_closest_response(
|
|
714
|
+
self, tracker: DialogueStateTracker
|
|
715
|
+
) -> Tuple[Optional[str], float]:
|
|
716
|
+
"""Find the closest response fitting the conversation in the tracker.
|
|
717
|
+
|
|
718
|
+
Generates a response using the OpenAI API and then finds the closest
|
|
719
|
+
response in the domains responses. The closest response is determined
|
|
720
|
+
using embeddings of the response and all the responses in the domain.
|
|
721
|
+
The embedding is generated using the OpenAI API and the HyDE model.
|
|
722
|
+
|
|
723
|
+
Args:
|
|
724
|
+
tracker: The tracker containing the conversation history up to now.
|
|
725
|
+
policy_model: The model's persisted data.
|
|
726
|
+
company: The company the model is used for.
|
|
727
|
+
|
|
728
|
+
Returns:
|
|
729
|
+
The response and the score of the response.
|
|
730
|
+
"""
|
|
731
|
+
if not self.response_index:
|
|
732
|
+
structlogger.debug("intentless_policy.prediction.skip_noresponses")
|
|
733
|
+
return None, 0.0
|
|
734
|
+
|
|
735
|
+
if not tracker.latest_message or not tracker.latest_message.text:
|
|
736
|
+
# we can't generate a response if there is no text on the latest
|
|
737
|
+
# user message
|
|
738
|
+
structlogger.debug("intentless_policy.prediction.skip_notext")
|
|
739
|
+
return None, 0.0
|
|
740
|
+
|
|
741
|
+
if tracker.latest_message.text.startswith("/"):
|
|
742
|
+
# we don't want to generate a response if the user is trying to
|
|
743
|
+
# execute a "command" - this should be handled by the regex
|
|
744
|
+
# intent classifier in rasa pro.
|
|
745
|
+
structlogger.debug("intentless_policy.prediction.skip_slash")
|
|
746
|
+
return None, 0.0
|
|
747
|
+
|
|
748
|
+
history = tracker_as_readable_transcript(tracker)
|
|
749
|
+
ai_response_examples = self.select_response_examples(
|
|
750
|
+
history,
|
|
751
|
+
number_of_samples=NUMBER_OF_RESPONSE_SAMPLES,
|
|
752
|
+
max_number_of_tokens=MAX_NUMBER_OF_TOKENS_FOR_SAMPLES,
|
|
753
|
+
)
|
|
754
|
+
conversation_samples = self.select_few_shot_conversations(
|
|
755
|
+
history,
|
|
756
|
+
number_of_samples=NUMBER_OF_CONVERSATION_SAMPLES,
|
|
757
|
+
max_number_of_tokens=MAX_NUMBER_OF_TOKENS_FOR_SAMPLES,
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
extra_ai_responses = self.extract_ai_responses(conversation_samples)
|
|
761
|
+
|
|
762
|
+
# put conversation responses in front of sampled examples,
|
|
763
|
+
# keeping the order of samples
|
|
764
|
+
final_response_examples = extra_ai_responses
|
|
765
|
+
for resp in ai_response_examples:
|
|
766
|
+
if resp not in final_response_examples:
|
|
767
|
+
final_response_examples.append(resp)
|
|
768
|
+
|
|
769
|
+
llm_response = await self.generate_answer(
|
|
770
|
+
final_response_examples, conversation_samples, history
|
|
771
|
+
)
|
|
772
|
+
if not llm_response:
|
|
773
|
+
structlogger.debug("intentless_policy.prediction.skip_llm_fail")
|
|
774
|
+
return None, 0.0
|
|
775
|
+
embedded_llm_response = self.embed_llm_response(llm_response)
|
|
776
|
+
if not embedded_llm_response:
|
|
777
|
+
structlogger.debug("intentless_policy.prediction.skip_response_embed_fail")
|
|
778
|
+
return None, 0.0
|
|
779
|
+
|
|
780
|
+
search_results = self.response_index.similarity_search_with_score_by_vector(
|
|
781
|
+
embedded_llm_response
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
return self._get_response_and_score(search_results, tracker)
|
|
785
|
+
|
|
786
|
+
def extract_ai_responses(self, conversation_samples: List[str]) -> List[str]:
|
|
787
|
+
"""Extracts the AI responses from the conversation samples.
|
|
788
|
+
|
|
789
|
+
Args:
|
|
790
|
+
conversation_samples: The conversation samples.
|
|
791
|
+
|
|
792
|
+
Returns:
|
|
793
|
+
The AI responses.
|
|
794
|
+
"""
|
|
795
|
+
ai_replies = []
|
|
796
|
+
|
|
797
|
+
for conversation_sample in conversation_samples:
|
|
798
|
+
ai_texts = extract_participant_messages_from_transcript(
|
|
799
|
+
conversation_sample, participant=AI
|
|
800
|
+
)
|
|
801
|
+
for ai_text in ai_texts:
|
|
802
|
+
if ai_text not in ai_replies:
|
|
803
|
+
ai_replies.append(ai_text)
|
|
804
|
+
return ai_replies
|
|
805
|
+
|
|
806
|
+
def _get_response_and_score(
|
|
807
|
+
self,
|
|
808
|
+
search_results: List[Tuple["Document", float]],
|
|
809
|
+
tracker: DialogueStateTracker,
|
|
810
|
+
) -> Tuple[Optional[str], float]:
|
|
811
|
+
"""Returns the response and score of the response.
|
|
812
|
+
|
|
813
|
+
If there are no search results, returns None for the response
|
|
814
|
+
and 0 for the score.
|
|
815
|
+
|
|
816
|
+
Args:
|
|
817
|
+
search_results: The search results.
|
|
818
|
+
tracker: The tracker containing the conversation history up to now.
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
Returns:
|
|
822
|
+
The response and the score of the response.
|
|
823
|
+
"""
|
|
824
|
+
if not search_results:
|
|
825
|
+
return None, 0.0
|
|
826
|
+
|
|
827
|
+
first_search_result = search_results[0]
|
|
828
|
+
document, l2dist = first_search_result
|
|
829
|
+
response = document.page_content
|
|
830
|
+
score = 1.0 - float(l2dist) / math.sqrt(2) # from L2 distance to score
|
|
831
|
+
|
|
832
|
+
if tracker.latest_message:
|
|
833
|
+
nlu_confidence = tracker.latest_message.intent.get(
|
|
834
|
+
PREDICTED_CONFIDENCE_KEY, 1.0
|
|
835
|
+
)
|
|
836
|
+
else:
|
|
837
|
+
nlu_confidence = 1.0
|
|
838
|
+
# --- If we have high NLU confidence, let rules / memo run the show
|
|
839
|
+
if nlu_confidence > self.nlu_abstention_threshold:
|
|
840
|
+
score = min(score, nlu_confidence - 0.01)
|
|
841
|
+
return response, score
|
|
842
|
+
|
|
843
|
+
def select_response_examples(
|
|
844
|
+
self,
|
|
845
|
+
history: str,
|
|
846
|
+
number_of_samples: int,
|
|
847
|
+
max_number_of_tokens: int,
|
|
848
|
+
) -> List[str]:
|
|
849
|
+
"""Samples responses that fit the current conversation.
|
|
850
|
+
|
|
851
|
+
Args:
|
|
852
|
+
history: The conversation history.
|
|
853
|
+
policy_model: The policy model.
|
|
854
|
+
number_of_samples: The number of samples to return.
|
|
855
|
+
max_number_of_tokens: Maximum number of tokens for responses.
|
|
856
|
+
|
|
857
|
+
Returns:
|
|
858
|
+
The sampled conversation in order of score decrease.
|
|
859
|
+
"""
|
|
860
|
+
if not self.response_index or not history:
|
|
861
|
+
return []
|
|
862
|
+
|
|
863
|
+
try:
|
|
864
|
+
embedding = self.embedder.embed_query(history)
|
|
865
|
+
except Exception as e:
|
|
866
|
+
structlogger.error(
|
|
867
|
+
"intentless_policy.select_response_examples.error", error=e
|
|
868
|
+
)
|
|
869
|
+
return []
|
|
870
|
+
|
|
871
|
+
docs = self.response_index.similarity_search_by_vector(
|
|
872
|
+
embedding, k=number_of_samples
|
|
873
|
+
)
|
|
874
|
+
structlogger.debug(
|
|
875
|
+
"intentless_policy.select_response_examples.success",
|
|
876
|
+
number_of_samples=number_of_samples,
|
|
877
|
+
docs=docs,
|
|
878
|
+
)
|
|
879
|
+
|
|
880
|
+
return [
|
|
881
|
+
document.page_content
|
|
882
|
+
for document in truncate_documents(
|
|
883
|
+
docs, max_number_of_tokens=max_number_of_tokens
|
|
884
|
+
)
|
|
885
|
+
]
|
|
886
|
+
|
|
887
|
+
def select_few_shot_conversations(
|
|
888
|
+
self,
|
|
889
|
+
history: str,
|
|
890
|
+
number_of_samples: int,
|
|
891
|
+
max_number_of_tokens: int,
|
|
892
|
+
) -> List[str]:
|
|
893
|
+
"""Samples conversations from the given conversation samples.
|
|
894
|
+
|
|
895
|
+
Excludes conversations without AI replies
|
|
896
|
+
|
|
897
|
+
Args:
|
|
898
|
+
history: The conversation history.
|
|
899
|
+
number_of_samples: The number of samples to return.
|
|
900
|
+
max_number_of_tokens: Maximum number of tokens for conversations.
|
|
901
|
+
|
|
902
|
+
Returns:
|
|
903
|
+
The sampled conversation ordered by similarity decrease.
|
|
904
|
+
"""
|
|
905
|
+
if not self.conversation_samples_index or not history:
|
|
906
|
+
return []
|
|
907
|
+
|
|
908
|
+
docs = self.conversation_samples_index.similarity_search(
|
|
909
|
+
history, k=number_of_samples
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
structlogger.debug(
|
|
913
|
+
"intentless_policy.sampled_conversation",
|
|
914
|
+
number_of_samples=number_of_samples,
|
|
915
|
+
docs=docs,
|
|
916
|
+
)
|
|
917
|
+
conversations = []
|
|
918
|
+
|
|
919
|
+
for doc in truncate_documents(docs, max_number_of_tokens=max_number_of_tokens):
|
|
920
|
+
conversations.append(doc.page_content)
|
|
921
|
+
return conversations
|
|
922
|
+
|
|
923
|
+
def _prediction_result(
|
|
924
|
+
self, action_name: Optional[Text], domain: Domain, score: Optional[float] = 1.0
|
|
925
|
+
) -> List[float]:
|
|
926
|
+
"""Creates a prediction result.
|
|
927
|
+
|
|
928
|
+
Args:
|
|
929
|
+
action_name: The name of the predicted action.
|
|
930
|
+
domain: The model's domain.
|
|
931
|
+
score: The score of the predicted action.
|
|
932
|
+
|
|
933
|
+
Resturns:
|
|
934
|
+
The prediction result where the score is used for one hot encoding.
|
|
935
|
+
"""
|
|
936
|
+
result = self._default_predictions(domain)
|
|
937
|
+
if action_name:
|
|
938
|
+
result[domain.index_for_action(action_name)] = score # type: ignore[assignment]
|
|
939
|
+
return result
|
|
940
|
+
|
|
941
|
+
@classmethod
|
|
942
|
+
def load(
|
|
943
|
+
cls,
|
|
944
|
+
config: Dict[Text, Any],
|
|
945
|
+
model_storage: ModelStorage,
|
|
946
|
+
resource: Resource,
|
|
947
|
+
execution_context: ExecutionContext,
|
|
948
|
+
**kwargs: Any,
|
|
949
|
+
) -> "IntentlessPolicy":
|
|
950
|
+
"""Loads a trained policy (see parent class for full docstring)."""
|
|
951
|
+
|
|
952
|
+
# Perform health checks of both LLM and embeddings client configs
|
|
953
|
+
cls._perform_health_checks(config, "intentless_policy.load")
|
|
954
|
+
|
|
955
|
+
responses_docsearch = None
|
|
956
|
+
samples_docsearch = None
|
|
957
|
+
prompt_template = None
|
|
958
|
+
try:
|
|
959
|
+
with model_storage.read_from(resource) as path:
|
|
960
|
+
responses_docsearch = load_faiss_vector_store(
|
|
961
|
+
path / "responses_faiss", cls._create_plain_embedder(config)
|
|
962
|
+
)
|
|
963
|
+
samples_docsearch = load_faiss_vector_store(
|
|
964
|
+
path / "samples_faiss", cls._create_plain_embedder(config)
|
|
965
|
+
)
|
|
966
|
+
|
|
967
|
+
# FIXME: This is a hack to make sure that the docsearches are
|
|
968
|
+
# normalized. unfortunatley langchain doesn't persist / load
|
|
969
|
+
# this parameter.
|
|
970
|
+
if responses_docsearch:
|
|
971
|
+
responses_docsearch._normalize_L2 = True # pylint: disable=protected-access
|
|
972
|
+
prompt_template = rasa.shared.utils.io.read_file(
|
|
973
|
+
path / INTENTLESS_PROMPT_TEMPLATE_FILE_NAME
|
|
974
|
+
)
|
|
975
|
+
except (ValueError, FileNotFoundError, FileIOException) as e:
|
|
976
|
+
structlogger.warning(
|
|
977
|
+
"intentless_policy.load.failed", error=e, resource_name=resource.name
|
|
978
|
+
)
|
|
979
|
+
|
|
980
|
+
return cls(
|
|
981
|
+
config,
|
|
982
|
+
model_storage,
|
|
983
|
+
resource,
|
|
984
|
+
execution_context,
|
|
985
|
+
responses_docsearch=responses_docsearch,
|
|
986
|
+
samples_docsearch=samples_docsearch,
|
|
987
|
+
prompt_template=prompt_template,
|
|
988
|
+
)
|
|
989
|
+
|
|
990
|
+
@classmethod
|
|
991
|
+
def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
|
|
992
|
+
"""Add a fingerprint of intentless policy for the graph."""
|
|
993
|
+
prompt_template = get_prompt_template(
|
|
994
|
+
config.get(PROMPT_CONFIG_KEY),
|
|
995
|
+
DEFAULT_INTENTLESS_PROMPT_TEMPLATE,
|
|
996
|
+
)
|
|
997
|
+
|
|
998
|
+
llm_config = resolve_model_client_config(
|
|
999
|
+
config.get(LLM_CONFIG_KEY), IntentlessPolicy.__name__
|
|
1000
|
+
)
|
|
1001
|
+
embedding_config = resolve_model_client_config(
|
|
1002
|
+
config.get(EMBEDDINGS_CONFIG_KEY), IntentlessPolicy.__name__
|
|
1003
|
+
)
|
|
1004
|
+
|
|
1005
|
+
return deep_container_fingerprint(
|
|
1006
|
+
[prompt_template, llm_config, embedding_config]
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
@classmethod
|
|
1010
|
+
def _perform_health_checks(
|
|
1011
|
+
cls, config: Dict[Text, Any], log_source_method: str
|
|
1012
|
+
) -> None:
|
|
1013
|
+
# Perform health check of the LLM client config
|
|
1014
|
+
llm_config = resolve_model_client_config(config.get(LLM_CONFIG_KEY, {}))
|
|
1015
|
+
cls.perform_llm_health_check(
|
|
1016
|
+
llm_config,
|
|
1017
|
+
DEFAULT_LLM_CONFIG,
|
|
1018
|
+
log_source_method,
|
|
1019
|
+
IntentlessPolicy.__name__,
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
# Perform health check of the embeddings client config
|
|
1023
|
+
embeddings_config = resolve_model_client_config(
|
|
1024
|
+
config.get(EMBEDDINGS_CONFIG_KEY, {})
|
|
1025
|
+
)
|
|
1026
|
+
cls.perform_embeddings_health_check(
|
|
1027
|
+
embeddings_config,
|
|
1028
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
1029
|
+
log_source_method,
|
|
1030
|
+
IntentlessPolicy.__name__,
|
|
1031
|
+
)
|