rasa-pro 3.12.0.dev2__py3-none-any.whl → 3.12.0.dev4__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.
- rasa/__main__.py +7 -7
- rasa/anonymization/anonymisation_rule_yaml_reader.py +1 -1
- rasa/anonymization/anonymization_pipeline.py +3 -3
- rasa/anonymization/anonymization_rule_executor.py +1 -1
- rasa/anonymization/anonymization_rule_orchestrator.py +2 -3
- rasa/cli/arguments/data.py +2 -2
- rasa/cli/arguments/evaluate.py +2 -1
- rasa/cli/arguments/interactive.py +1 -1
- rasa/cli/arguments/run.py +1 -1
- rasa/cli/arguments/test.py +7 -5
- rasa/cli/arguments/train.py +3 -3
- rasa/cli/arguments/visualize.py +2 -2
- rasa/cli/arguments/x.py +1 -0
- rasa/cli/data.py +4 -3
- rasa/cli/dialogue_understanding_test.py +121 -18
- rasa/cli/evaluate.py +1 -1
- rasa/cli/export.py +6 -6
- rasa/cli/interactive.py +4 -5
- rasa/cli/llm_fine_tuning.py +5 -5
- rasa/cli/markers.py +1 -2
- rasa/cli/project_templates/calm/actions/add_contact.py +1 -1
- rasa/cli/project_templates/tutorial/actions/actions.py +3 -2
- rasa/cli/shell.py +2 -3
- rasa/cli/studio/download.py +1 -2
- rasa/cli/studio/studio.py +2 -3
- rasa/cli/studio/train.py +0 -1
- rasa/cli/telemetry.py +2 -2
- rasa/cli/test.py +11 -11
- rasa/cli/utils.py +7 -5
- rasa/core/__init__.py +0 -1
- rasa/core/actions/action.py +42 -21
- rasa/core/actions/action_hangup.py +1 -1
- rasa/core/actions/action_repeat_bot_messages.py +2 -2
- rasa/core/actions/action_run_slot_rejections.py +2 -2
- rasa/core/actions/action_trigger_chitchat.py +1 -1
- rasa/core/actions/action_trigger_flow.py +5 -5
- rasa/core/actions/action_trigger_search.py +1 -1
- rasa/core/actions/forms.py +14 -12
- rasa/core/actions/http_custom_action_executor.py +8 -1
- rasa/core/actions/loops.py +3 -3
- rasa/core/actions/two_stage_fallback.py +13 -13
- rasa/core/auth_retry_tracker_store.py +1 -2
- rasa/core/brokers/broker.py +2 -1
- rasa/core/brokers/file.py +1 -1
- rasa/core/brokers/kafka.py +8 -8
- rasa/core/brokers/pika.py +8 -9
- rasa/core/brokers/sql.py +4 -3
- rasa/core/channels/__init__.py +3 -0
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/callback.py +4 -4
- rasa/core/channels/channel.py +11 -11
- rasa/core/channels/console.py +0 -1
- rasa/core/channels/development_inspector.py +6 -6
- rasa/core/channels/facebook.py +5 -5
- rasa/core/channels/hangouts.py +7 -8
- rasa/core/channels/inspector/dist/assets/{arc-861ddd57.js → arc-632a63ec.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-921f02db.js → c4Diagram-d0fbc5ce-081e0df4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-b436c4f8.js → classDiagram-936ed81e-3df0afc2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-511a23cb.js → classDiagram-v2-c3cb15f1-8c5ed31e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-ef476ecd.js → createText-62fc7601-89c73b31.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-f1878e0a.js → edges-f2ad444c-4fc48c3e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-fac75185.js → erDiagram-9d236eb7-907e0440.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-201c5bbc.js → flowDb-1972c806-9ec53a3c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-f904ae41.js → flowDiagram-7ea5b25a-41da787a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-8bea338b.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-1813da66.js → flowchart-elk-definition-abe16c3d-ce370633.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-872af172.js → ganttDiagram-9b5ea136-90a36523.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-34a0af5a.js → gitGraphDiagram-99d0ae7c-41e1aa3f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-42ba3e3d.js → index-2c4b9a3b-e6f2af62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-37817b51.js → index-e793d777.js} +3 -3
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-6b731386.js → infoDiagram-736b4530-8ceba4db.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-e8579ac6.js → journeyDiagram-df861f2b-960d3809.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-89e6403a.js → layout-498807d8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-dc73d3fc.js → line-eeccc4e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-f5b1d2bc.js → linear-8a078617.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-82cb74fa.js → mindmap-definition-beec6740-396d17dd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-bdf5f29b.js → pieDiagram-dbbf0591-dc9b5e1b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-c7a0cbe4.js → quadrantDiagram-4d7f4fd6-a08cba6d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-7ec5410f.js → requirementDiagram-6fc4c22a-87242b9e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-caee5554.js → sankeyDiagram-8f13d901-53f6f391.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-2935f8db.js → sequenceDiagram-b655622a-715c9c20.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-8f5d9693.js → stateDiagram-59f0c015-2e8fb31f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-d565d1de.js → stateDiagram-v2-2b26beab-7e2d2aa0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-75ad421d.js → styles-080da4f6-4420cea6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-7e764226.js → styles-3dcbcfbf-28676cf4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-7a4e0e61.js → styles-9c745c82-cef936a6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-4019d1bf.js → svgDrawCommon-4835440b-151251e9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-01ea12df.js → timeline-definition-5b62e21b-0d39bdb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-89407137.js → xychartDiagram-2b33534f-a03fa445.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +3 -1
- rasa/core/channels/inspector/index.html +2 -0
- rasa/core/channels/inspector/src/App.tsx +1 -4
- rasa/core/channels/mattermost.py +4 -4
- rasa/core/channels/rasa_chat.py +4 -4
- rasa/core/channels/rest.py +11 -12
- rasa/core/channels/rocketchat.py +4 -3
- rasa/core/channels/slack.py +6 -5
- rasa/core/channels/socketio.py +7 -28
- rasa/core/channels/studio_chat.py +193 -0
- rasa/core/channels/telegram.py +73 -41
- rasa/core/channels/twilio.py +3 -3
- rasa/core/channels/vier_cvg.py +2 -2
- rasa/core/channels/voice_ready/audiocodes.py +8 -8
- rasa/core/channels/voice_ready/jambonz.py +5 -5
- rasa/core/channels/voice_ready/jambonz_protocol.py +3 -4
- rasa/core/channels/voice_ready/twilio_voice.py +9 -8
- rasa/core/channels/voice_ready/utils.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +2 -2
- rasa/core/channels/voice_stream/asr/azure.py +2 -2
- rasa/core/channels/voice_stream/asr/deepgram.py +57 -16
- rasa/core/channels/voice_stream/browser_audio.py +9 -6
- rasa/core/channels/voice_stream/call_state.py +2 -1
- rasa/core/channels/voice_stream/tts/azure.py +1 -2
- rasa/core/channels/voice_stream/tts/cartesia.py +5 -4
- rasa/core/channels/voice_stream/tts/tts_cache.py +3 -2
- rasa/core/channels/voice_stream/tts/tts_engine.py +1 -1
- rasa/core/channels/voice_stream/twilio_media_streams.py +10 -7
- rasa/core/channels/voice_stream/util.py +1 -1
- rasa/core/channels/voice_stream/voice_channel.py +15 -15
- rasa/core/channels/webexteams.py +3 -4
- rasa/core/evaluation/marker.py +7 -6
- rasa/core/evaluation/marker_base.py +15 -16
- rasa/core/evaluation/marker_stats.py +3 -4
- rasa/core/evaluation/marker_tracker_loader.py +5 -4
- rasa/core/exporter.py +4 -4
- rasa/core/featurizers/precomputation.py +8 -8
- rasa/core/featurizers/single_state_featurizer.py +7 -7
- rasa/core/featurizers/tracker_featurizers.py +13 -13
- rasa/core/http_interpreter.py +3 -4
- rasa/core/information_retrieval/__init__.py +1 -1
- rasa/core/information_retrieval/faiss.py +4 -4
- rasa/core/information_retrieval/information_retrieval.py +2 -2
- rasa/core/information_retrieval/milvus.py +3 -3
- rasa/core/information_retrieval/qdrant.py +3 -3
- rasa/core/jobs.py +1 -0
- rasa/core/lock.py +2 -3
- rasa/core/lock_store.py +3 -3
- rasa/core/migrate.py +11 -8
- rasa/core/nlg/__init__.py +1 -1
- rasa/core/nlg/callback.py +2 -3
- rasa/core/nlg/contextual_response_rephraser.py +63 -13
- rasa/core/nlg/generator.py +2 -2
- rasa/core/nlg/interpolator.py +4 -3
- rasa/core/nlg/response.py +3 -4
- rasa/core/nlg/summarize.py +1 -0
- rasa/core/persistor.py +3 -3
- rasa/core/policies/ensemble.py +10 -9
- rasa/core/policies/enterprise_search_policy.py +86 -21
- rasa/core/policies/flow_policy.py +13 -14
- rasa/core/policies/flows/flow_executor.py +35 -11
- rasa/core/policies/intentless_policy.py +6 -7
- rasa/core/policies/memoization.py +22 -20
- rasa/core/policies/policy.py +24 -22
- rasa/core/policies/rule_policy.py +37 -36
- rasa/core/policies/ted_policy.py +87 -85
- rasa/core/policies/unexpected_intent_policy.py +77 -75
- rasa/core/processor.py +96 -65
- rasa/core/run.py +1 -1
- rasa/core/secrets_manager/endpoints.py +2 -3
- rasa/core/secrets_manager/factory.py +2 -3
- rasa/core/secrets_manager/secret_manager.py +2 -3
- rasa/core/secrets_manager/vault.py +2 -2
- rasa/core/test.py +30 -30
- rasa/core/tracker_store.py +15 -15
- rasa/core/train.py +1 -1
- rasa/core/training/__init__.py +2 -2
- rasa/core/training/converters/responses_prefix_converter.py +1 -2
- rasa/core/training/interactive.py +13 -13
- rasa/core/training/story_conflict.py +4 -5
- rasa/core/training/training.py +3 -5
- rasa/core/utils.py +5 -5
- rasa/core/visualize.py +1 -1
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -2
- rasa/dialogue_understanding/coexistence/llm_based_router.py +5 -5
- rasa/dialogue_understanding/commands/__init__.py +22 -22
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -1
- rasa/dialogue_understanding/commands/cancel_flow_command.py +18 -7
- rasa/dialogue_understanding/commands/change_flow_command.py +18 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +18 -4
- rasa/dialogue_understanding/commands/clarify_command.py +19 -3
- rasa/dialogue_understanding/commands/command.py +19 -3
- rasa/dialogue_understanding/commands/correct_slots_command.py +3 -3
- rasa/dialogue_understanding/commands/error_command.py +1 -1
- rasa/dialogue_understanding/commands/free_form_answer_command.py +2 -1
- rasa/dialogue_understanding/commands/handle_code_change_command.py +2 -2
- rasa/dialogue_understanding/commands/human_handoff_command.py +16 -4
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +18 -4
- rasa/dialogue_understanding/commands/noop_command.py +2 -1
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +16 -4
- rasa/dialogue_understanding/commands/restart_command.py +2 -5
- rasa/dialogue_understanding/commands/session_end_command.py +3 -5
- rasa/dialogue_understanding/commands/session_start_command.py +3 -5
- rasa/dialogue_understanding/commands/set_slot_command.py +27 -3
- rasa/dialogue_understanding/commands/skip_question_command.py +16 -4
- rasa/dialogue_understanding/commands/start_flow_command.py +17 -2
- rasa/dialogue_understanding/commands/user_silence_command.py +3 -5
- rasa/dialogue_understanding/commands/utils.py +64 -45
- rasa/dialogue_understanding/constants.py +1 -0
- rasa/dialogue_understanding/generator/command_generator.py +2 -119
- rasa/dialogue_understanding/generator/command_parser.py +201 -0
- rasa/dialogue_understanding/generator/constants.py +2 -2
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -7
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +11 -57
- rasa/dialogue_understanding/generator/llm_command_generator.py +2 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +67 -120
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +8 -10
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +32 -93
- rasa/dialogue_understanding/generator/utils.py +45 -0
- rasa/dialogue_understanding/patterns/cancel.py +2 -1
- rasa/dialogue_understanding/patterns/cannot_handle.py +1 -0
- rasa/dialogue_understanding/patterns/chitchat.py +1 -1
- rasa/dialogue_understanding/patterns/clarify.py +2 -1
- rasa/dialogue_understanding/patterns/code_change.py +2 -0
- rasa/dialogue_understanding/patterns/collect_information.py +6 -3
- rasa/dialogue_understanding/patterns/completed.py +1 -1
- rasa/dialogue_understanding/patterns/continue_interrupted.py +10 -1
- rasa/dialogue_understanding/patterns/correction.py +4 -2
- rasa/dialogue_understanding/patterns/human_handoff.py +1 -1
- rasa/dialogue_understanding/patterns/internal_error.py +1 -0
- rasa/dialogue_understanding/patterns/search.py +1 -1
- rasa/dialogue_understanding/patterns/session_start.py +1 -1
- rasa/dialogue_understanding/patterns/skip_question.py +1 -0
- rasa/dialogue_understanding/patterns/user_silence.py +1 -1
- rasa/dialogue_understanding/processor/command_processor.py +13 -9
- rasa/dialogue_understanding/processor/command_processor_component.py +1 -1
- rasa/dialogue_understanding/stack/dialogue_stack.py +4 -3
- rasa/dialogue_understanding/stack/frames/__init__.py +2 -2
- rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +4 -1
- rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +2 -3
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +5 -2
- rasa/dialogue_understanding/stack/frames/search_frame.py +4 -1
- rasa/dialogue_understanding/stack/utils.py +8 -4
- rasa/dialogue_understanding/utils.py +121 -2
- rasa/dialogue_understanding_test/README.md +379 -0
- rasa/dialogue_understanding_test/command_comparison.py +60 -0
- rasa/dialogue_understanding_test/command_metric_calculation.py +110 -4
- rasa/dialogue_understanding_test/constants.py +6 -1
- rasa/dialogue_understanding_test/du_test_case.py +252 -38
- rasa/dialogue_understanding_test/du_test_result.py +291 -2
- rasa/dialogue_understanding_test/du_test_runner.py +239 -10
- rasa/dialogue_understanding_test/du_test_schema.yml +161 -0
- rasa/dialogue_understanding_test/io.py +338 -20
- rasa/dialogue_understanding_test/test_case_simulation/__init__.py +0 -0
- rasa/dialogue_understanding_test/test_case_simulation/exception.py +28 -0
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +336 -0
- rasa/dialogue_understanding_test/utils.py +70 -0
- rasa/dialogue_understanding_test/validation.py +59 -4
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -1
- rasa/e2e_test/assertions.py +1 -1
- rasa/e2e_test/e2e_config.py +1 -1
- rasa/e2e_test/e2e_test_case.py +3 -4
- rasa/e2e_test/e2e_test_converter.py +2 -3
- rasa/e2e_test/e2e_test_coverage_report.py +6 -6
- rasa/e2e_test/e2e_test_result.py +1 -1
- rasa/e2e_test/e2e_test_runner.py +134 -31
- rasa/e2e_test/stub_custom_action.py +1 -1
- rasa/e2e_test/utils/e2e_yaml_utils.py +1 -1
- rasa/e2e_test/utils/io.py +132 -65
- rasa/e2e_test/utils/validation.py +1 -1
- rasa/engine/caching.py +5 -7
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +2 -2
- rasa/engine/recipes/default_components.py +13 -15
- rasa/engine/recipes/recipe.py +2 -2
- rasa/engine/runner/dask.py +2 -2
- rasa/engine/runner/interface.py +1 -0
- rasa/engine/storage/local_model_storage.py +5 -4
- rasa/engine/storage/resource.py +2 -1
- rasa/engine/storage/storage.py +5 -3
- rasa/engine/training/components.py +2 -1
- rasa/engine/training/fingerprinting.py +4 -2
- rasa/engine/training/graph_trainer.py +4 -4
- rasa/engine/training/hooks.py +2 -2
- rasa/engine/validation.py +34 -33
- rasa/exceptions.py +3 -2
- rasa/graph_components/converters/nlu_message_converter.py +3 -3
- rasa/graph_components/providers/domain_for_core_training_provider.py +3 -3
- rasa/graph_components/providers/domain_provider.py +3 -2
- rasa/graph_components/providers/flows_provider.py +2 -3
- rasa/graph_components/providers/forms_provider.py +4 -4
- rasa/graph_components/providers/nlu_training_data_provider.py +5 -3
- rasa/graph_components/providers/responses_provider.py +4 -4
- rasa/graph_components/providers/rule_only_provider.py +3 -2
- rasa/graph_components/providers/story_graph_provider.py +8 -8
- rasa/graph_components/providers/training_tracker_provider.py +3 -2
- rasa/graph_components/validators/default_recipe_validator.py +16 -16
- rasa/graph_components/validators/finetuning_validator.py +10 -8
- rasa/hooks.py +18 -12
- rasa/jupyter.py +2 -2
- rasa/llm_fine_tuning/annotation_module.py +4 -4
- rasa/llm_fine_tuning/conversations.py +6 -6
- rasa/llm_fine_tuning/llm_data_preparation_module.py +1 -1
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -4
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +1 -1
- rasa/llm_fine_tuning/paraphrasing_module.py +1 -1
- rasa/llm_fine_tuning/storage.py +3 -3
- rasa/markers/marker.py +2 -3
- rasa/markers/marker_base.py +1 -2
- rasa/markers/upload.py +2 -2
- rasa/markers/validate.py +2 -3
- rasa/model.py +3 -5
- rasa/model_manager/config.py +1 -1
- rasa/model_manager/model_api.py +5 -4
- rasa/model_manager/runner_service.py +6 -6
- rasa/model_manager/socket_bridge.py +8 -3
- rasa/model_manager/studio_jwt_auth.py +1 -0
- rasa/model_manager/trainer_service.py +9 -7
- rasa/model_manager/utils.py +1 -1
- rasa/model_manager/warm_rasa_process.py +14 -8
- rasa/model_service.py +5 -6
- rasa/model_testing.py +13 -15
- rasa/nlu/classifiers/diet_classifier.py +72 -73
- rasa/nlu/classifiers/fallback_classifier.py +9 -11
- rasa/nlu/classifiers/keyword_intent_classifier.py +7 -6
- rasa/nlu/classifiers/logistic_regression_classifier.py +3 -3
- rasa/nlu/classifiers/mitie_intent_classifier.py +5 -4
- rasa/nlu/classifiers/regex_message_handler.py +3 -2
- rasa/nlu/classifiers/sklearn_intent_classifier.py +2 -2
- rasa/nlu/convert.py +2 -2
- rasa/nlu/emulators/dialogflow.py +3 -3
- rasa/nlu/emulators/luis.py +5 -5
- rasa/nlu/emulators/no_emulator.py +1 -0
- rasa/nlu/emulators/wit.py +4 -4
- rasa/nlu/extractors/crf_entity_extractor.py +11 -11
- rasa/nlu/extractors/duckling_entity_extractor.py +7 -6
- rasa/nlu/extractors/entity_synonyms.py +10 -9
- rasa/nlu/extractors/extractor.py +16 -16
- rasa/nlu/extractors/mitie_entity_extractor.py +10 -9
- rasa/nlu/extractors/regex_entity_extractor.py +11 -10
- rasa/nlu/extractors/spacy_entity_extractor.py +2 -2
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +15 -14
- rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +2 -1
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +10 -9
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +9 -7
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +13 -12
- rasa/nlu/featurizers/featurizer.py +5 -4
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +6 -6
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -4
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +4 -4
- rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +2 -0
- rasa/nlu/model.py +0 -1
- rasa/nlu/selectors/response_selector.py +67 -68
- rasa/nlu/test.py +38 -38
- rasa/nlu/tokenizers/jieba_tokenizer.py +1 -2
- rasa/nlu/tokenizers/mitie_tokenizer.py +2 -2
- rasa/nlu/tokenizers/spacy_tokenizer.py +3 -3
- rasa/nlu/tokenizers/tokenizer.py +6 -7
- rasa/nlu/tokenizers/whitespace_tokenizer.py +1 -1
- rasa/nlu/utils/bilou_utils.py +7 -7
- rasa/nlu/utils/hugging_face/registry.py +22 -22
- rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +2 -1
- rasa/nlu/utils/mitie_utils.py +2 -1
- rasa/nlu/utils/pattern_utils.py +1 -1
- rasa/nlu/utils/spacy_utils.py +3 -3
- rasa/plugin.py +12 -1
- rasa/server.py +37 -1
- rasa/shared/constants.py +22 -2
- rasa/shared/core/command_payload_reader.py +15 -7
- rasa/shared/core/constants.py +4 -1
- rasa/shared/core/conversation.py +1 -2
- rasa/shared/core/events.py +47 -37
- rasa/shared/core/flows/__init__.py +0 -1
- rasa/shared/core/flows/flow.py +11 -11
- rasa/shared/core/flows/flow_step.py +19 -13
- rasa/shared/core/flows/flow_step_links.py +21 -14
- rasa/shared/core/flows/flow_step_sequence.py +6 -4
- rasa/shared/core/flows/flows_list.py +3 -3
- rasa/shared/core/flows/nlu_trigger.py +1 -1
- rasa/shared/core/flows/steps/__init__.py +2 -2
- rasa/shared/core/flows/steps/action.py +4 -3
- rasa/shared/core/flows/steps/call.py +4 -4
- rasa/shared/core/flows/steps/collect.py +7 -4
- rasa/shared/core/flows/steps/continuation.py +3 -1
- rasa/shared/core/flows/steps/end.py +3 -1
- rasa/shared/core/flows/steps/internal.py +3 -2
- rasa/shared/core/flows/steps/link.py +6 -4
- rasa/shared/core/flows/steps/no_operation.py +7 -5
- rasa/shared/core/flows/steps/set_slots.py +4 -3
- rasa/shared/core/flows/steps/start.py +3 -1
- rasa/shared/core/flows/utils.py +1 -0
- rasa/shared/core/flows/validation.py +3 -5
- rasa/shared/core/generator.py +20 -21
- rasa/shared/core/slot_mappings.py +15 -15
- rasa/shared/core/slots.py +3 -3
- rasa/shared/core/trackers.py +31 -31
- rasa/shared/core/training_data/loading.py +1 -1
- rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
- rasa/shared/core/training_data/story_reader/story_step_builder.py +4 -4
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +29 -31
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +22 -24
- rasa/shared/core/training_data/structures.py +11 -12
- rasa/shared/core/training_data/visualization.py +10 -10
- rasa/shared/data.py +6 -6
- rasa/shared/engine/caching.py +0 -1
- rasa/shared/exceptions.py +2 -2
- rasa/shared/importers/rasa.py +5 -6
- rasa/shared/importers/utils.py +1 -1
- rasa/shared/nlu/constants.py +3 -0
- rasa/shared/nlu/training_data/entities_parser.py +6 -6
- rasa/shared/nlu/training_data/features.py +3 -3
- rasa/shared/nlu/training_data/formats/__init__.py +1 -1
- rasa/shared/nlu/training_data/formats/dialogflow.py +4 -5
- rasa/shared/nlu/training_data/formats/luis.py +7 -8
- rasa/shared/nlu/training_data/formats/rasa.py +4 -5
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +17 -16
- rasa/shared/nlu/training_data/formats/readerwriter.py +8 -11
- rasa/shared/nlu/training_data/formats/wit.py +3 -4
- rasa/shared/nlu/training_data/loading.py +4 -4
- rasa/shared/nlu/training_data/lookup_tables_parser.py +1 -1
- rasa/shared/nlu/training_data/message.py +13 -14
- rasa/shared/nlu/training_data/schemas/data_schema.py +1 -1
- rasa/shared/nlu/training_data/schemas/responses.yml +1 -0
- rasa/shared/nlu/training_data/synonyms_parser.py +3 -3
- rasa/shared/nlu/training_data/training_data.py +12 -13
- rasa/shared/nlu/training_data/util.py +11 -10
- rasa/shared/providers/_configs/azure_openai_client_config.py +3 -119
- rasa/shared/providers/_configs/client_config.py +1 -3
- rasa/shared/providers/_configs/default_litellm_client_config.py +1 -3
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -3
- rasa/shared/providers/_configs/litellm_router_client_config.py +1 -3
- rasa/shared/providers/_configs/model_group_config.py +2 -7
- rasa/shared/providers/_configs/openai_client_config.py +1 -3
- rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -3
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -3
- rasa/shared/providers/_configs/utils.py +1 -0
- rasa/shared/providers/_ssl_verification_utils.py +5 -6
- rasa/shared/providers/_utils.py +5 -5
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -1
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +3 -26
- rasa/shared/providers/embedding/embedding_client.py +1 -1
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +1 -3
- rasa/shared/providers/llm/_base_litellm_client.py +1 -3
- rasa/shared/providers/llm/azure_openai_llm_client.py +25 -79
- rasa/shared/providers/llm/default_litellm_llm_client.py +1 -3
- rasa/shared/providers/llm/litellm_router_llm_client.py +2 -21
- rasa/shared/providers/llm/llm_client.py +1 -3
- rasa/shared/providers/llm/llm_response.py +41 -2
- rasa/shared/providers/llm/openai_llm_client.py +3 -9
- rasa/shared/providers/llm/rasa_llm_client.py +6 -20
- rasa/shared/providers/llm/self_hosted_llm_client.py +3 -9
- rasa/shared/providers/mappings.py +18 -19
- rasa/shared/providers/router/_base_litellm_router_client.py +1 -3
- rasa/shared/providers/router/router_client.py +1 -3
- rasa/shared/utils/cli.py +1 -1
- rasa/shared/utils/common.py +1 -1
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +1 -1
- rasa/shared/utils/health_check/health_check.py +3 -3
- rasa/shared/utils/health_check/llm_health_check_mixin.py +1 -1
- rasa/shared/utils/io.py +1 -1
- rasa/shared/utils/llm.py +5 -9
- rasa/shared/utils/pykwalify_extensions.py +1 -1
- rasa/shared/utils/schemas/events.py +1 -1
- rasa/shared/utils/yaml.py +29 -26
- rasa/studio/auth.py +3 -3
- rasa/studio/config.py +1 -2
- rasa/studio/data_handler.py +3 -3
- rasa/studio/download.py +1 -1
- rasa/studio/results_logger.py +3 -3
- rasa/studio/upload.py +2 -0
- rasa/telemetry.py +31 -0
- rasa/tracing/config.py +3 -3
- rasa/tracing/instrumentation/attribute_extractors.py +54 -0
- rasa/tracing/instrumentation/instrumentation.py +25 -5
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +1 -1
- rasa/tracing/instrumentation/metrics.py +11 -11
- rasa/tracing/metric_instrument_provider.py +14 -14
- rasa/utils/common.py +12 -9
- rasa/utils/endpoints.py +1 -1
- rasa/utils/io.py +7 -7
- rasa/utils/licensing.py +3 -4
- rasa/utils/log_utils.py +7 -6
- rasa/utils/ml_utils.py +1 -0
- rasa/utils/plotting.py +3 -3
- rasa/utils/sanic_error_handler.py +1 -1
- rasa/utils/tensorflow/callback.py +2 -2
- rasa/utils/tensorflow/crf.py +2 -2
- rasa/utils/tensorflow/data_generator.py +5 -5
- rasa/utils/tensorflow/environment.py +3 -3
- rasa/utils/tensorflow/feature_array.py +2 -3
- rasa/utils/tensorflow/layers.py +18 -12
- rasa/utils/tensorflow/layers_utils.py +2 -1
- rasa/utils/tensorflow/metrics.py +2 -2
- rasa/utils/tensorflow/model_data.py +7 -7
- rasa/utils/tensorflow/model_data_utils.py +10 -9
- rasa/utils/tensorflow/models.py +31 -32
- rasa/utils/tensorflow/rasa_layers.py +20 -19
- rasa/utils/tensorflow/types.py +2 -1
- rasa/utils/train_utils.py +23 -21
- rasa/utils/url_tools.py +1 -1
- rasa/validator.py +17 -1
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev4.dist-info}/METADATA +9 -10
- rasa_pro-3.12.0.dev4.dist-info/RECORD +800 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +0 -1
- rasa/shared/providers/_configs/azure_entra_id_client_creds.py +0 -40
- rasa/shared/providers/_configs/azure_entra_id_config.py +0 -533
- rasa/shared/providers/_configs/oauth_config.py +0 -33
- rasa/shared/providers/constants.py +0 -6
- rasa_pro-3.12.0.dev2.dist-info/RECORD +0 -793
- {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev4.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev4.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev4.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
|
|
4
|
+
import structlog
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from rasa.core.agent import Agent
|
|
8
|
+
from rasa.core.channels import CollectingOutputChannel, UserMessage
|
|
9
|
+
from rasa.dialogue_understanding.commands import Command, SetSlotCommand
|
|
10
|
+
from rasa.dialogue_understanding.commands.set_slot_command import SetSlotExtractor
|
|
11
|
+
from rasa.dialogue_understanding_test.constants import (
|
|
12
|
+
PLACEHOLDER_GENERATED_ANSWER_TEMPLATE,
|
|
13
|
+
)
|
|
14
|
+
from rasa.dialogue_understanding_test.du_test_case import (
|
|
15
|
+
DialogueUnderstandingTestCase,
|
|
16
|
+
DialogueUnderstandingTestStep,
|
|
17
|
+
)
|
|
18
|
+
from rasa.dialogue_understanding_test.test_case_simulation.exception import (
|
|
19
|
+
TestCaseTrackerSimulatorException,
|
|
20
|
+
)
|
|
21
|
+
from rasa.dialogue_understanding_test.utils import filter_metadata
|
|
22
|
+
from rasa.e2e_test.e2e_test_case import Fixture, Metadata
|
|
23
|
+
from rasa.shared.core.constants import MAPPING_TYPE, SlotMappingType
|
|
24
|
+
from rasa.shared.core.events import BotUttered, SlotSet, UserUttered
|
|
25
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
26
|
+
from rasa.shared.nlu.constants import COMMANDS, ENTITIES, INTENT
|
|
27
|
+
|
|
28
|
+
structlogger = structlog.get_logger()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TestCaseTrackerSimulatorResult(BaseModel):
|
|
32
|
+
sender_id: str
|
|
33
|
+
user_uttered_event_indices: List[int]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TestCaseTrackerSimulator:
|
|
37
|
+
"""Builds up a tracker for a test case.
|
|
38
|
+
|
|
39
|
+
The tracker is built up by simulating a conversation with the bot
|
|
40
|
+
using the user and bot steps of the test case.
|
|
41
|
+
As the user steps are annotated with commands, the user messages
|
|
42
|
+
are sent to the bot with the commands, i.e. skipping any LLM call.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
agent: Agent,
|
|
48
|
+
test_case: DialogueUnderstandingTestCase,
|
|
49
|
+
output_channel: Optional[CollectingOutputChannel] = None,
|
|
50
|
+
):
|
|
51
|
+
self.agent = agent
|
|
52
|
+
self.test_case = test_case
|
|
53
|
+
self.output_channel = output_channel or CollectingOutputChannel()
|
|
54
|
+
|
|
55
|
+
self.sender_id = self._generate_sender_id()
|
|
56
|
+
|
|
57
|
+
async def simulate_test_case(
|
|
58
|
+
self,
|
|
59
|
+
metadata: List[Metadata],
|
|
60
|
+
) -> TestCaseTrackerSimulatorResult:
|
|
61
|
+
"""Simulates a conversation with the bot using the test case.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
metadata: The available metadata.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
The result of the simulation.
|
|
68
|
+
"""
|
|
69
|
+
step_index = 0
|
|
70
|
+
user_uttered_event_indices: List[int] = []
|
|
71
|
+
|
|
72
|
+
while step_index < len(self.test_case.steps):
|
|
73
|
+
user_step, bot_steps = self.test_case.get_next_user_and_bot_steps(
|
|
74
|
+
step_index
|
|
75
|
+
)
|
|
76
|
+
if user_step is None:
|
|
77
|
+
raise TestCaseTrackerSimulatorException(
|
|
78
|
+
test_case_name=self.test_case.full_name(),
|
|
79
|
+
failure_reason="Could not retrieve next user step.",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
step_index += len(bot_steps) + 1 # for the user step
|
|
83
|
+
|
|
84
|
+
# we don't need to simulate the last user message
|
|
85
|
+
if step_index >= len(self.test_case.steps):
|
|
86
|
+
tracker = await self.agent.tracker_store.retrieve(self.sender_id)
|
|
87
|
+
if tracker is None:
|
|
88
|
+
raise TestCaseTrackerSimulatorException(
|
|
89
|
+
test_case_name=self.test_case.full_name(),
|
|
90
|
+
user_message=user_step.text,
|
|
91
|
+
failure_reason="The tracker could not be retrieved.",
|
|
92
|
+
)
|
|
93
|
+
# add the index of the last user uttered event
|
|
94
|
+
user_uttered_event_indices.append(len(tracker.events))
|
|
95
|
+
|
|
96
|
+
return TestCaseTrackerSimulatorResult(
|
|
97
|
+
sender_id=self.sender_id,
|
|
98
|
+
user_uttered_event_indices=user_uttered_event_indices,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# send the user message to the agent
|
|
102
|
+
try:
|
|
103
|
+
await self._send_user_message_with_commands(
|
|
104
|
+
user_step,
|
|
105
|
+
metadata,
|
|
106
|
+
)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
raise TestCaseTrackerSimulatorException(
|
|
109
|
+
test_case_name=self.test_case.full_name(),
|
|
110
|
+
user_message=user_step.text,
|
|
111
|
+
failure_reason="Sending the user message failed.",
|
|
112
|
+
original_exception=e.__dict__,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
tracker = await self.agent.tracker_store.retrieve(self.sender_id)
|
|
116
|
+
if tracker is None:
|
|
117
|
+
raise TestCaseTrackerSimulatorException(
|
|
118
|
+
test_case_name=self.test_case.full_name(),
|
|
119
|
+
user_message=user_step.text,
|
|
120
|
+
failure_reason="The tracker could not be retrieved.",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# add latest user uttered event index to the list
|
|
124
|
+
user_uttered_event_indices.append(
|
|
125
|
+
await self._get_latest_user_uttered_event_index(
|
|
126
|
+
tracker, user_uttered_event_indices
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# check if bot responses match the expected bot steps
|
|
131
|
+
if not self._do_bot_responses_match(tracker, bot_steps):
|
|
132
|
+
structlogger.error(
|
|
133
|
+
"dialogue_understanding_test.tracker_simulator.stop_simulation.bot_utterance_mismatch",
|
|
134
|
+
test_case=self.test_case.full_name(),
|
|
135
|
+
user_message=user_step.text,
|
|
136
|
+
bot_steps=bot_steps,
|
|
137
|
+
bot_uttered_events=TestCaseTrackerSimulator._get_latest_bot_uttered_events(
|
|
138
|
+
tracker
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
# stop the simulation if the bot responses do not match
|
|
142
|
+
# we can still test the steps up until the mismatch
|
|
143
|
+
return TestCaseTrackerSimulatorResult(
|
|
144
|
+
sender_id=self.sender_id,
|
|
145
|
+
user_uttered_event_indices=user_uttered_event_indices,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
return TestCaseTrackerSimulatorResult(
|
|
149
|
+
sender_id=self.sender_id,
|
|
150
|
+
user_uttered_event_indices=user_uttered_event_indices,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def _generate_sender_id(self) -> str:
|
|
154
|
+
# add timestamp suffix to ensure sender_id is unique
|
|
155
|
+
return f"{self.test_case.name}_{datetime.now()}"
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
async def _get_latest_user_uttered_event_index(
|
|
159
|
+
tracker: DialogueStateTracker, user_uttered_event_indices: List[int]
|
|
160
|
+
) -> int:
|
|
161
|
+
"""Get the index of the latest user uttered event in the tracker."""
|
|
162
|
+
# search the tracker events for the latest user message starting from the
|
|
163
|
+
# index of the user message before
|
|
164
|
+
# +1 to avoid getting the same index for duplicate user messages,
|
|
165
|
+
# such as, "yes"
|
|
166
|
+
from_index = (
|
|
167
|
+
user_uttered_event_indices[-1] + 1 if user_uttered_event_indices else 0
|
|
168
|
+
)
|
|
169
|
+
return tracker.events.index(tracker.latest_message, from_index)
|
|
170
|
+
|
|
171
|
+
def _do_bot_responses_match(
|
|
172
|
+
self,
|
|
173
|
+
tracker: DialogueStateTracker,
|
|
174
|
+
bot_steps: List[DialogueUnderstandingTestStep],
|
|
175
|
+
) -> bool:
|
|
176
|
+
# get all bot uttered events until the last user message
|
|
177
|
+
bot_uttered_events = self._get_latest_bot_uttered_events(tracker)
|
|
178
|
+
|
|
179
|
+
if len(bot_uttered_events) != len(bot_steps):
|
|
180
|
+
return False
|
|
181
|
+
|
|
182
|
+
for step in bot_steps:
|
|
183
|
+
if step.template:
|
|
184
|
+
if not self._does_template_match(step, bot_uttered_events):
|
|
185
|
+
return False
|
|
186
|
+
elif step.text:
|
|
187
|
+
if not self._does_text_match(step, bot_uttered_events):
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
return True
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
def _does_template_match(
|
|
194
|
+
step: DialogueUnderstandingTestStep, bot_uttered_events: List[BotUttered]
|
|
195
|
+
) -> bool:
|
|
196
|
+
for event in bot_uttered_events:
|
|
197
|
+
if step.template == PLACEHOLDER_GENERATED_ANSWER_TEMPLATE:
|
|
198
|
+
return True
|
|
199
|
+
elif "utter_action" not in event.metadata:
|
|
200
|
+
# a chitchat or knowledge base command was triggered,
|
|
201
|
+
# or the response comes from a custom action,
|
|
202
|
+
# continue with the simulation
|
|
203
|
+
return True
|
|
204
|
+
elif event.metadata["utter_action"] == step.template:
|
|
205
|
+
return True
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def _does_text_match(
|
|
210
|
+
step: DialogueUnderstandingTestStep, bot_uttered_events: List[BotUttered]
|
|
211
|
+
) -> bool:
|
|
212
|
+
for event in bot_uttered_events:
|
|
213
|
+
if event.text == step.text:
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
return False
|
|
217
|
+
|
|
218
|
+
@staticmethod
|
|
219
|
+
def _get_latest_bot_uttered_events(
|
|
220
|
+
tracker: DialogueStateTracker,
|
|
221
|
+
) -> List[BotUttered]:
|
|
222
|
+
"""Get the latest bot uttered events in the tracker."""
|
|
223
|
+
# collect all bot uttered events until a user uttered event is reached
|
|
224
|
+
# starting from the end of the tracker events
|
|
225
|
+
bot_uttered_events = []
|
|
226
|
+
for event in reversed(tracker.events):
|
|
227
|
+
if isinstance(event, BotUttered):
|
|
228
|
+
bot_uttered_events.append(event)
|
|
229
|
+
if isinstance(event, UserUttered):
|
|
230
|
+
break
|
|
231
|
+
return bot_uttered_events
|
|
232
|
+
|
|
233
|
+
async def initialize_tracker(self, fixtures: List[Fixture]) -> None:
|
|
234
|
+
"""Initializes a new tracker with fixtures."""
|
|
235
|
+
assert self.agent.processor is not None
|
|
236
|
+
|
|
237
|
+
tracker = await self.agent.processor.fetch_tracker_with_initial_session(
|
|
238
|
+
self.sender_id, output_channel=self.output_channel
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
if fixtures and self.test_case.fixture_names:
|
|
242
|
+
test_fixtures = self._filter_fixtures_for_test_case(
|
|
243
|
+
self.test_case.fixture_names, fixtures
|
|
244
|
+
)
|
|
245
|
+
await self._set_up_fixtures(test_fixtures, tracker)
|
|
246
|
+
|
|
247
|
+
# store the tracker with the unique sender id
|
|
248
|
+
await self.agent.tracker_store.save(tracker)
|
|
249
|
+
|
|
250
|
+
async def _set_up_fixtures(
|
|
251
|
+
self,
|
|
252
|
+
fixtures: List[Fixture],
|
|
253
|
+
tracker: DialogueStateTracker,
|
|
254
|
+
) -> None:
|
|
255
|
+
"""Sets up fixtures in the tracker."""
|
|
256
|
+
if not fixtures or not self.agent.processor:
|
|
257
|
+
return
|
|
258
|
+
|
|
259
|
+
for fixture in fixtures:
|
|
260
|
+
for slot_name, slot_value in fixture.slots_set.items():
|
|
261
|
+
tracker.update(SlotSet(slot_name, slot_value))
|
|
262
|
+
|
|
263
|
+
@staticmethod
|
|
264
|
+
def _filter_fixtures_for_test_case(
|
|
265
|
+
fixture_names: Optional[List[str]], fixtures: List[Fixture]
|
|
266
|
+
) -> List[Fixture]:
|
|
267
|
+
"""Filters fixtures applicable to the test case."""
|
|
268
|
+
return [
|
|
269
|
+
fixture
|
|
270
|
+
for fixture in fixtures
|
|
271
|
+
if fixture_names and fixture.name in fixture_names
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
async def _send_user_message_with_commands(
|
|
275
|
+
self,
|
|
276
|
+
user_step: DialogueUnderstandingTestStep,
|
|
277
|
+
metadata: List[Metadata],
|
|
278
|
+
) -> None:
|
|
279
|
+
"""Sends a user message with commands to the agent."""
|
|
280
|
+
user_message = self._create_user_message(user_step, metadata)
|
|
281
|
+
await self.agent.handle_message(user_message)
|
|
282
|
+
|
|
283
|
+
def _create_user_message(
|
|
284
|
+
self,
|
|
285
|
+
user_step: DialogueUnderstandingTestStep,
|
|
286
|
+
metadata: List[Metadata],
|
|
287
|
+
) -> UserMessage:
|
|
288
|
+
"""Creates a user message with commands."""
|
|
289
|
+
user_message = user_step.text
|
|
290
|
+
# Get the metadata for the step
|
|
291
|
+
metadata_for_step = filter_metadata(
|
|
292
|
+
self.test_case, user_step, metadata, self.sender_id
|
|
293
|
+
)
|
|
294
|
+
# Update the extractor of SetSlotCommand based on the slot mapping type
|
|
295
|
+
commands = self._update_extractor_of_set_slot_commands(
|
|
296
|
+
user_step.commands, user_message
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
return UserMessage(
|
|
300
|
+
user_message,
|
|
301
|
+
self.output_channel,
|
|
302
|
+
self.sender_id,
|
|
303
|
+
parse_data={
|
|
304
|
+
INTENT: {},
|
|
305
|
+
ENTITIES: [],
|
|
306
|
+
COMMANDS: [command.as_dict() for command in commands],
|
|
307
|
+
},
|
|
308
|
+
metadata=metadata_for_step,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
def _update_extractor_of_set_slot_commands(
|
|
312
|
+
self, commands: List[Command], user_message: str
|
|
313
|
+
) -> List[Command]:
|
|
314
|
+
"""Update the extractor for SetSlotCommand based on the slot mapping type."""
|
|
315
|
+
slots = []
|
|
316
|
+
if self.agent.domain is not None:
|
|
317
|
+
slots = self.agent.domain.slots
|
|
318
|
+
|
|
319
|
+
for command in commands:
|
|
320
|
+
if isinstance(command, SetSlotCommand):
|
|
321
|
+
slot_definition = next(
|
|
322
|
+
(slot for slot in slots if slot.name == command.name), slots[0]
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Use the SetSlotExtractor.COMMAND_PAYLOAD_READER extractor if the user
|
|
326
|
+
# message starts with the /SetSlot.
|
|
327
|
+
if user_message.startswith(r"/SetSlot"):
|
|
328
|
+
command.extractor = SetSlotExtractor.COMMAND_PAYLOAD_READER.value
|
|
329
|
+
# Use the SetSlotExtractor.NLU extractor if the slot mapping type is
|
|
330
|
+
# not FROM_LLM.
|
|
331
|
+
elif SlotMappingType.FROM_LLM.value not in [
|
|
332
|
+
mapping[MAPPING_TYPE] for mapping in slot_definition.mappings
|
|
333
|
+
]:
|
|
334
|
+
command.extractor = SetSlotExtractor.NLU.value
|
|
335
|
+
|
|
336
|
+
return commands
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from typing import Dict, List, Tuple
|
|
2
|
+
|
|
3
|
+
from rasa.dialogue_understanding_test.du_test_case import (
|
|
4
|
+
DialogueUnderstandingTestCase,
|
|
5
|
+
DialogueUnderstandingTestStep,
|
|
6
|
+
)
|
|
7
|
+
from rasa.e2e_test.e2e_test_case import Metadata
|
|
8
|
+
from rasa.e2e_test.e2e_test_runner import E2ETestRunner
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def filter_metadata(
|
|
12
|
+
test_case: DialogueUnderstandingTestCase,
|
|
13
|
+
user_step: DialogueUnderstandingTestStep,
|
|
14
|
+
metadata: List[Metadata],
|
|
15
|
+
sender_id: str,
|
|
16
|
+
) -> Dict[str, str]:
|
|
17
|
+
"""Filter metadata for a test case and a step."""
|
|
18
|
+
# test case metadata
|
|
19
|
+
test_case_metadata = E2ETestRunner.filter_metadata_for_input(
|
|
20
|
+
test_case.metadata_name, metadata
|
|
21
|
+
)
|
|
22
|
+
test_case_metadata_dict = test_case_metadata.metadata if test_case_metadata else {}
|
|
23
|
+
|
|
24
|
+
# step metadata
|
|
25
|
+
step_metadata = E2ETestRunner.filter_metadata_for_input(
|
|
26
|
+
user_step.metadata_name, metadata
|
|
27
|
+
)
|
|
28
|
+
step_metadata_dict = step_metadata.metadata if step_metadata else {}
|
|
29
|
+
|
|
30
|
+
# merge metadata
|
|
31
|
+
return E2ETestRunner.merge_metadata(
|
|
32
|
+
sender_id, user_step.text, test_case_metadata_dict, step_metadata_dict
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_command_comparison(step: DialogueUnderstandingTestStep) -> List[str]:
|
|
37
|
+
expected_commands = (
|
|
38
|
+
[command.to_dsl() for command in step.commands] if step.commands else []
|
|
39
|
+
)
|
|
40
|
+
predicted_commands = [command.to_dsl() for command in step.get_predicted_commands()]
|
|
41
|
+
|
|
42
|
+
expected_commands.insert(0, "---EXPECTED---")
|
|
43
|
+
predicted_commands.insert(0, "---PREDICTED---")
|
|
44
|
+
|
|
45
|
+
max_line_length = max(len(line) for line in expected_commands)
|
|
46
|
+
expected_commands, predicted_commands = make_lists_equal(
|
|
47
|
+
expected_commands, predicted_commands
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
command_comparison = []
|
|
51
|
+
for i, (expected_line, actual_line) in enumerate(
|
|
52
|
+
zip(expected_commands, predicted_commands)
|
|
53
|
+
):
|
|
54
|
+
expected_line += " " * (max_line_length - len(expected_line))
|
|
55
|
+
if i == 0:
|
|
56
|
+
# make the first line red:
|
|
57
|
+
expected_line = "[red3]" + expected_line + "[/red3]"
|
|
58
|
+
actual_line = "[red3]" + actual_line + "[/red3]"
|
|
59
|
+
command_comparison.append(f"{expected_line} | {actual_line}")
|
|
60
|
+
|
|
61
|
+
return command_comparison
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def make_lists_equal(list1: List[str], list2: List[str]) -> Tuple[List[str], List[str]]:
|
|
65
|
+
if len(list1) < len(list2):
|
|
66
|
+
list1.extend([""] * (len(list2) - len(list1)))
|
|
67
|
+
return list1, list2
|
|
68
|
+
|
|
69
|
+
list2.extend([""] * (len(list1) - len(list2)))
|
|
70
|
+
return list1, list2
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import argparse
|
|
2
|
-
|
|
2
|
+
import sys
|
|
3
|
+
from typing import List, Optional
|
|
3
4
|
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from rasa.dialogue_understanding_test.constants import (
|
|
8
|
+
ACTOR_BOT,
|
|
9
|
+
PLACEHOLDER_GENERATED_ANSWER_TEMPLATE,
|
|
10
|
+
)
|
|
4
11
|
from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
|
|
12
|
+
from rasa.shared.core.domain import Domain
|
|
13
|
+
|
|
14
|
+
structlogger = structlog.get_logger()
|
|
5
15
|
|
|
6
16
|
|
|
7
17
|
def validate_cli_arguments(args: argparse.Namespace) -> None:
|
|
@@ -10,13 +20,58 @@ def validate_cli_arguments(args: argparse.Namespace) -> None:
|
|
|
10
20
|
Args:
|
|
11
21
|
args: Commandline arguments.
|
|
12
22
|
"""
|
|
13
|
-
|
|
23
|
+
# Model path, endpoints file path, and the path to test cases are validated
|
|
24
|
+
# in other places.
|
|
25
|
+
# Validate remote storage option
|
|
26
|
+
supported_remote_storages = ["aws", "gcs", "azure"]
|
|
27
|
+
if (
|
|
28
|
+
args.remote_storage
|
|
29
|
+
and args.remote_storage.lower() not in supported_remote_storages
|
|
30
|
+
):
|
|
31
|
+
structlogger.error(
|
|
32
|
+
"dialogue_understanding_test.validate_cli_arguments.invalid_remote_storage",
|
|
33
|
+
event_info=(
|
|
34
|
+
f"Invalid remote storage option - '{args.remote_storage}'. Supported "
|
|
35
|
+
f"options are: {supported_remote_storages}"
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
sys.exit(1)
|
|
14
39
|
|
|
15
40
|
|
|
16
|
-
def validate_test_cases(
|
|
41
|
+
def validate_test_cases(
|
|
42
|
+
test_cases: List[DialogueUnderstandingTestCase], domain: Optional[Domain]
|
|
43
|
+
) -> None:
|
|
17
44
|
"""Validate the dialogue understanding test cases.
|
|
18
45
|
|
|
19
46
|
Args:
|
|
20
47
|
test_cases: Test cases to validate.
|
|
48
|
+
domain: Domain of the assistant.
|
|
21
49
|
"""
|
|
22
|
-
|
|
50
|
+
if not domain:
|
|
51
|
+
structlogger.error(
|
|
52
|
+
"dialogue_understanding_test.validate_test_cases.no_domain",
|
|
53
|
+
event_info="No domain found. Retrain the model with a valid domain.",
|
|
54
|
+
)
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
# Retrieve all valid templates from the domain
|
|
58
|
+
valid_templates = domain.utterances_for_response
|
|
59
|
+
|
|
60
|
+
# Add 'placeholder_generated_answer' as a valid template
|
|
61
|
+
valid_templates.add(PLACEHOLDER_GENERATED_ANSWER_TEMPLATE)
|
|
62
|
+
|
|
63
|
+
for test_case in test_cases:
|
|
64
|
+
for step in test_case.steps:
|
|
65
|
+
if step.actor == ACTOR_BOT and step.template:
|
|
66
|
+
if step.template not in valid_templates:
|
|
67
|
+
structlogger.error(
|
|
68
|
+
"dialogue_understanding_test.validate_test_cases.invalid_template",
|
|
69
|
+
event_info=(
|
|
70
|
+
f"Invalid bot utterance template '{step.template}' in test "
|
|
71
|
+
f"case '{test_case.name}' at line {step.line}. Please "
|
|
72
|
+
f"the template exists."
|
|
73
|
+
),
|
|
74
|
+
test_case=test_case.name,
|
|
75
|
+
template=step.template,
|
|
76
|
+
)
|
|
77
|
+
sys.exit(1)
|
rasa/e2e_test/assertions.py
CHANGED
rasa/e2e_test/e2e_config.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Any, Dict, Generator, Optional
|
|
7
7
|
|
|
8
8
|
import structlog
|
|
9
9
|
from pydantic import BaseModel
|
rasa/e2e_test/e2e_test_case.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from collections import OrderedDict
|
|
2
|
-
from collections import defaultdict
|
|
1
|
+
from collections import OrderedDict, defaultdict
|
|
3
2
|
from dataclasses import dataclass
|
|
4
3
|
from typing import Any, Dict, List, Optional, Text, Union
|
|
5
4
|
|
|
@@ -8,16 +7,16 @@ import structlog
|
|
|
8
7
|
from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
|
|
9
8
|
from rasa.e2e_test.assertions import Assertion
|
|
10
9
|
from rasa.e2e_test.constants import (
|
|
11
|
-
KEY_ASSERTIONS,
|
|
12
10
|
KEY_ASSERTION_ORDER_ENABLED,
|
|
11
|
+
KEY_ASSERTIONS,
|
|
13
12
|
KEY_BOT_INPUT,
|
|
14
13
|
KEY_BOT_UTTERED,
|
|
15
14
|
KEY_FIXTURES,
|
|
16
15
|
KEY_METADATA,
|
|
17
|
-
KEY_STUB_CUSTOM_ACTIONS,
|
|
18
16
|
KEY_SLOT_NOT_SET,
|
|
19
17
|
KEY_SLOT_SET,
|
|
20
18
|
KEY_STEPS,
|
|
19
|
+
KEY_STUB_CUSTOM_ACTIONS,
|
|
21
20
|
KEY_TEST_CASE,
|
|
22
21
|
KEY_TEST_CASES,
|
|
23
22
|
KEY_USER_INPUT,
|
|
@@ -5,8 +5,7 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from importlib.resources import read_text
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from textwrap import dedent
|
|
8
|
-
from typing import
|
|
9
|
-
from typing import Optional
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
10
9
|
|
|
11
10
|
import pandas as pd
|
|
12
11
|
import ruamel
|
|
@@ -21,8 +20,8 @@ from rasa.e2e_test.utils.validation import read_e2e_test_schema
|
|
|
21
20
|
from rasa.exceptions import RasaException
|
|
22
21
|
from rasa.shared.utils.llm import llm_factory
|
|
23
22
|
from rasa.shared.utils.yaml import (
|
|
24
|
-
validate_yaml_data_using_schema_with_assertions,
|
|
25
23
|
YamlValidationException,
|
|
24
|
+
validate_yaml_data_using_schema_with_assertions,
|
|
26
25
|
)
|
|
27
26
|
|
|
28
27
|
structlogger = structlog.get_logger()
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Dict, List, Optional, Set
|
|
2
2
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import structlog
|
|
5
5
|
|
|
6
6
|
from rasa.dialogue_understanding.commands import (
|
|
7
|
-
KnowledgeAnswerCommand,
|
|
8
|
-
StartFlowCommand,
|
|
9
|
-
SetSlotCommand,
|
|
10
|
-
ClarifyCommand,
|
|
11
|
-
HumanHandoffCommand,
|
|
12
7
|
CancelFlowCommand,
|
|
13
8
|
ChitChatAnswerCommand,
|
|
9
|
+
ClarifyCommand,
|
|
10
|
+
HumanHandoffCommand,
|
|
11
|
+
KnowledgeAnswerCommand,
|
|
12
|
+
SetSlotCommand,
|
|
14
13
|
SkipQuestionCommand,
|
|
14
|
+
StartFlowCommand,
|
|
15
15
|
)
|
|
16
16
|
from rasa.e2e_test.e2e_test_result import TestResult
|
|
17
17
|
from rasa.shared.core.flows import FlowsList
|
rasa/e2e_test/e2e_test_result.py
CHANGED