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
|
@@ -1,11 +1,300 @@
|
|
|
1
|
-
|
|
1
|
+
import typing
|
|
2
|
+
from typing import Any, Dict, List, Optional, Text
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
|
|
5
|
-
from rasa.
|
|
6
|
+
from rasa.dialogue_understanding.commands import Command
|
|
7
|
+
from rasa.dialogue_understanding_test.du_test_case import (
|
|
8
|
+
DialogueUnderstandingTestCase,
|
|
9
|
+
DialogueUnderstandingTestStep,
|
|
10
|
+
)
|
|
11
|
+
from rasa.dialogue_understanding_test.utils import get_command_comparison
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from rasa.dialogue_understanding_test.command_metric_calculation import (
|
|
15
|
+
CommandMetrics,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
KEY_TEST_CASES_ACCURACY = "test_cases"
|
|
19
|
+
KEY_USER_UTTERANCES_ACCURACY = "user_utterances"
|
|
20
|
+
|
|
21
|
+
OUTPUT_NUMBER_OF_FAILED_TESTS = "number_of_failed_tests"
|
|
22
|
+
OUTPUT_NUMBER_OF_PASSED_TESTS = "number_of_passed_tests"
|
|
23
|
+
OUTPUT_TEST_CASES_ACCURACY = "test_cases_accuracy"
|
|
24
|
+
OUTPUT_USER_UTTERANCES_ACCURACY = "user_utterances_accuracy"
|
|
25
|
+
OUTPUT_NUMBER_OF_PASSED_USER_UTTERANCES = "number_of_passed_user_utterances"
|
|
26
|
+
OUTPUT_NUMBER_OF_FAILED_USER_UTTERANCES = "number_of_failed_user_utterances"
|
|
27
|
+
OUTPUT_COMMAND_METRICS = "command_metrics"
|
|
28
|
+
OUTPUT_NAMES_OF_FAILED_TESTS = "names_of_failed_tests"
|
|
29
|
+
OUTPUT_NAMES_OF_PASSED_TESTS = "names_of_passed_tests"
|
|
6
30
|
|
|
7
31
|
|
|
8
32
|
class DialogueUnderstandingTestResult(BaseModel):
|
|
33
|
+
"""Result of a single dialogue understanding test case."""
|
|
34
|
+
|
|
9
35
|
test_case: DialogueUnderstandingTestCase
|
|
10
36
|
passed: bool
|
|
11
37
|
error_line: Optional[int] = None
|
|
38
|
+
|
|
39
|
+
def get_expected_commands(self) -> List[Command]:
|
|
40
|
+
return self.test_case.get_expected_commands()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class FailedTestStep(BaseModel):
|
|
44
|
+
"""Failed test step information."""
|
|
45
|
+
|
|
46
|
+
file: str
|
|
47
|
+
test_case_name: str
|
|
48
|
+
failed_user_utterance: str
|
|
49
|
+
error_line: int
|
|
50
|
+
pass_status: bool
|
|
51
|
+
command_generators: List[str]
|
|
52
|
+
prompt: Optional[Dict[str, Any]] = None
|
|
53
|
+
expected_commands: List[Command]
|
|
54
|
+
predicted_commands: Dict[str, List[Command]]
|
|
55
|
+
conversation_with_diff: List[str]
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_dialogue_understanding_test_step(
|
|
59
|
+
cls,
|
|
60
|
+
step: DialogueUnderstandingTestStep,
|
|
61
|
+
test_case: DialogueUnderstandingTestCase,
|
|
62
|
+
) -> "FailedTestStep":
|
|
63
|
+
file_path = test_case.file or ""
|
|
64
|
+
user_utterance = step.text or ""
|
|
65
|
+
line_number = step.line or -1
|
|
66
|
+
|
|
67
|
+
predicted_commands: Dict[str, List[Command]] = {}
|
|
68
|
+
prompts: Optional[Dict[str, Any]] = None
|
|
69
|
+
command_generators: List[str] = []
|
|
70
|
+
|
|
71
|
+
if step.dialogue_understanding_output:
|
|
72
|
+
predicted_commands = step.dialogue_understanding_output.commands
|
|
73
|
+
command_generators = step.dialogue_understanding_output.get_component_names_that_predicted_commands() # noqa: E501
|
|
74
|
+
prompts = (
|
|
75
|
+
step.dialogue_understanding_output.get_component_name_to_user_prompts()
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
step_index = test_case.steps.index(step)
|
|
79
|
+
|
|
80
|
+
conversation_with_diff = test_case.to_readable_conversation(
|
|
81
|
+
until_step=step_index + 1
|
|
82
|
+
) + get_command_comparison(step)
|
|
83
|
+
|
|
84
|
+
return cls(
|
|
85
|
+
file=file_path,
|
|
86
|
+
test_case_name=test_case.name,
|
|
87
|
+
failed_user_utterance=user_utterance,
|
|
88
|
+
error_line=line_number,
|
|
89
|
+
pass_status=False,
|
|
90
|
+
command_generators=command_generators,
|
|
91
|
+
prompt=prompts,
|
|
92
|
+
expected_commands=step.commands or [],
|
|
93
|
+
predicted_commands=predicted_commands,
|
|
94
|
+
conversation_with_diff=conversation_with_diff,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def to_dict(self, output_prompt: bool) -> Dict[Text, Any]:
|
|
98
|
+
step_info = {
|
|
99
|
+
"file": self.file,
|
|
100
|
+
"test_case": self.test_case_name,
|
|
101
|
+
"failed_user_utterance": self.failed_user_utterance,
|
|
102
|
+
"error_line": self.error_line,
|
|
103
|
+
"pass_status": self.pass_status,
|
|
104
|
+
"expected_commands": [
|
|
105
|
+
command.to_dsl() for command in self.expected_commands
|
|
106
|
+
],
|
|
107
|
+
"predicted_commands": [
|
|
108
|
+
{
|
|
109
|
+
"component": component,
|
|
110
|
+
"commands": [command.to_dsl() for command in commands],
|
|
111
|
+
}
|
|
112
|
+
for component, commands in self.predicted_commands.items()
|
|
113
|
+
if commands
|
|
114
|
+
],
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if output_prompt and self.prompt:
|
|
118
|
+
step_info["prompts"] = [
|
|
119
|
+
{
|
|
120
|
+
component: [
|
|
121
|
+
{
|
|
122
|
+
"prompt_name": prompt_name,
|
|
123
|
+
"prompt_content": prompt_content,
|
|
124
|
+
}
|
|
125
|
+
for prompt_name, prompt_content in prompts
|
|
126
|
+
],
|
|
127
|
+
}
|
|
128
|
+
for component, prompts in self.prompt.items()
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
return step_info
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class DialogueUnderstandingTestSuiteResult:
|
|
135
|
+
"""Result of a dialogue understanding test suite.
|
|
136
|
+
|
|
137
|
+
Aggregates test results and provides metrics for the entire test suite
|
|
138
|
+
used to log the results to the console and write them to a file.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self) -> None:
|
|
142
|
+
self.accuracy = {
|
|
143
|
+
KEY_TEST_CASES_ACCURACY: 0.0,
|
|
144
|
+
KEY_USER_UTTERANCES_ACCURACY: 0.0,
|
|
145
|
+
}
|
|
146
|
+
self.number_of_passed_tests = 0
|
|
147
|
+
self.number_of_failed_tests = 0
|
|
148
|
+
self.number_of_passed_user_utterances = 0
|
|
149
|
+
self.number_of_failed_user_utterances = 0
|
|
150
|
+
self.command_metrics: Optional[Dict[str, "CommandMetrics"]] = None
|
|
151
|
+
self.names_of_failed_tests: List[str] = []
|
|
152
|
+
self.names_of_passed_tests: List[str] = []
|
|
153
|
+
self.failed_test_steps: List[FailedTestStep] = []
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
def from_results(
|
|
157
|
+
cls,
|
|
158
|
+
failing_test_results: List[DialogueUnderstandingTestResult],
|
|
159
|
+
passing_test_results: List[DialogueUnderstandingTestResult],
|
|
160
|
+
command_metrics: Dict[str, "CommandMetrics"],
|
|
161
|
+
) -> "DialogueUnderstandingTestSuiteResult":
|
|
162
|
+
"""Create a DialogueUnderstandingTestSuiteResult object from the test results.
|
|
163
|
+
|
|
164
|
+
Create a new instance of DialogueUnderstandingTestSuiteResult by aggregating
|
|
165
|
+
metrics from passing and failing test results, along with command metrics.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
failing_test_results: A list of DialogueUnderstandingTestResult objects
|
|
169
|
+
representing the test cases that did not pass.
|
|
170
|
+
passing_test_results: A list of DialogueUnderstandingTestResult objects
|
|
171
|
+
representing the test cases that passed.
|
|
172
|
+
command_metrics: A dictionary of command-specific performance metrics, keyed
|
|
173
|
+
by command name.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
A DialogueUnderstandingTestSuiteResult object containing aggregated test
|
|
177
|
+
suite metrics, including accuracy, counts of passed and failed test cases,
|
|
178
|
+
user utterance statistics, and command metrics.
|
|
179
|
+
"""
|
|
180
|
+
instance = cls()
|
|
181
|
+
|
|
182
|
+
instance.number_of_passed_tests = len(passing_test_results)
|
|
183
|
+
instance.number_of_failed_tests = len(failing_test_results)
|
|
184
|
+
instance.accuracy[KEY_TEST_CASES_ACCURACY] = instance.number_of_passed_tests / (
|
|
185
|
+
instance.number_of_passed_tests + instance.number_of_failed_tests
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
instance._set_user_utterance_metrics(failing_test_results, passing_test_results)
|
|
189
|
+
|
|
190
|
+
instance.command_metrics = command_metrics
|
|
191
|
+
|
|
192
|
+
instance.names_of_passed_tests = [
|
|
193
|
+
passing_test_result.test_case.full_name()
|
|
194
|
+
for passing_test_result in passing_test_results
|
|
195
|
+
]
|
|
196
|
+
instance.names_of_failed_tests = [
|
|
197
|
+
failing_test_result.test_case.full_name()
|
|
198
|
+
for failing_test_result in failing_test_results
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
instance.failed_test_steps = cls._create_failed_steps_from_results(
|
|
202
|
+
failing_test_results
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return instance
|
|
206
|
+
|
|
207
|
+
def _set_user_utterance_metrics(
|
|
208
|
+
self,
|
|
209
|
+
failing_test_results: List[DialogueUnderstandingTestResult],
|
|
210
|
+
passing_test_results: List[DialogueUnderstandingTestResult],
|
|
211
|
+
) -> None:
|
|
212
|
+
# Create list of booleans indicating whether each user utterance
|
|
213
|
+
# passed or failed
|
|
214
|
+
user_utterances_status = [
|
|
215
|
+
step.has_passed()
|
|
216
|
+
for test in failing_test_results + passing_test_results
|
|
217
|
+
for step in test.test_case.iterate_over_user_steps()
|
|
218
|
+
]
|
|
219
|
+
# Calculate number of passed and failed user utterances
|
|
220
|
+
self.number_of_passed_user_utterances = sum(user_utterances_status)
|
|
221
|
+
self.number_of_failed_user_utterances = (
|
|
222
|
+
len(user_utterances_status) - self.number_of_passed_user_utterances
|
|
223
|
+
)
|
|
224
|
+
# Calculate user utterance accuracy
|
|
225
|
+
self.accuracy[KEY_USER_UTTERANCES_ACCURACY] = (
|
|
226
|
+
self.number_of_passed_user_utterances
|
|
227
|
+
/ (
|
|
228
|
+
self.number_of_failed_user_utterances
|
|
229
|
+
+ self.number_of_passed_user_utterances
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
@staticmethod
|
|
234
|
+
def _create_failed_steps_from_results(
|
|
235
|
+
failing_test_results: List["DialogueUnderstandingTestResult"],
|
|
236
|
+
) -> List[FailedTestStep]:
|
|
237
|
+
"""Create list of FailedTestStep objects from failing test results.
|
|
238
|
+
|
|
239
|
+
Given a list of failing DialogueUnderstandingTestResult objects,
|
|
240
|
+
create and return a list of FailedTestStep objects for each failing user step.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
failing_test_results: Results of failing Dialogue Understanding tests.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
List of aggregated FailedTestStep objects for logging to console and file.
|
|
247
|
+
"""
|
|
248
|
+
failed_test_steps: List[FailedTestStep] = []
|
|
249
|
+
|
|
250
|
+
for result in failing_test_results:
|
|
251
|
+
test_case = result.test_case
|
|
252
|
+
for step in test_case.failed_user_steps():
|
|
253
|
+
failed_test_steps.append(
|
|
254
|
+
FailedTestStep.from_dialogue_understanding_test_step(
|
|
255
|
+
step, test_case
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
return failed_test_steps
|
|
260
|
+
|
|
261
|
+
def to_dict(self, output_prompt: bool = False) -> Dict[Text, Any]:
|
|
262
|
+
"""Builds a dictionary for writing test results to a YML file.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
output_prompt: Whether to log the prompt or not.
|
|
266
|
+
"""
|
|
267
|
+
# 1. Accuracy block
|
|
268
|
+
result_dict: Dict[Text, Any] = {
|
|
269
|
+
"accuracy": {
|
|
270
|
+
"test_cases": self.accuracy[KEY_TEST_CASES_ACCURACY],
|
|
271
|
+
"user_utterances": self.accuracy[KEY_USER_UTTERANCES_ACCURACY],
|
|
272
|
+
},
|
|
273
|
+
OUTPUT_NUMBER_OF_PASSED_TESTS: self.number_of_passed_tests,
|
|
274
|
+
OUTPUT_NUMBER_OF_FAILED_TESTS: self.number_of_failed_tests,
|
|
275
|
+
OUTPUT_NUMBER_OF_PASSED_USER_UTTERANCES: self.number_of_passed_user_utterances, # noqa: E501
|
|
276
|
+
OUTPUT_NUMBER_OF_FAILED_USER_UTTERANCES: self.number_of_failed_user_utterances, # noqa: E501
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
cmd_metrics_output = {}
|
|
280
|
+
if self.command_metrics:
|
|
281
|
+
if isinstance(self.command_metrics, dict):
|
|
282
|
+
for cmd_name, metrics_obj in self.command_metrics.items():
|
|
283
|
+
cmd_metrics_output[cmd_name] = metrics_obj.as_dict()
|
|
284
|
+
else:
|
|
285
|
+
pass
|
|
286
|
+
|
|
287
|
+
result_dict[OUTPUT_COMMAND_METRICS] = cmd_metrics_output
|
|
288
|
+
|
|
289
|
+
result_dict[OUTPUT_NAMES_OF_PASSED_TESTS] = self.names_of_passed_tests
|
|
290
|
+
result_dict[OUTPUT_NAMES_OF_FAILED_TESTS] = self.names_of_failed_tests
|
|
291
|
+
|
|
292
|
+
failed_steps_list = []
|
|
293
|
+
for failed_test_step in self.failed_test_steps:
|
|
294
|
+
failed_steps_list.append(
|
|
295
|
+
failed_test_step.to_dict(output_prompt=output_prompt)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
result_dict["failed_test_steps"] = failed_steps_list
|
|
299
|
+
|
|
300
|
+
return result_dict
|
|
@@ -1,32 +1,52 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Any, Dict, List, Optional, Text
|
|
3
3
|
|
|
4
4
|
import structlog
|
|
5
|
+
from tqdm import tqdm
|
|
5
6
|
|
|
7
|
+
from rasa.core.channels import CollectingOutputChannel, UserMessage
|
|
6
8
|
from rasa.core.exceptions import AgentNotReady
|
|
7
9
|
from rasa.core.persistor import StorageType
|
|
8
10
|
from rasa.core.utils import AvailableEndpoints
|
|
9
|
-
from rasa.
|
|
11
|
+
from rasa.dialogue_understanding.commands import Command
|
|
12
|
+
from rasa.dialogue_understanding.utils import set_record_commands_and_prompts
|
|
13
|
+
from rasa.dialogue_understanding_test.du_test_case import (
|
|
14
|
+
DialogueUnderstandingOutput,
|
|
15
|
+
DialogueUnderstandingTestCase,
|
|
16
|
+
DialogueUnderstandingTestStep,
|
|
17
|
+
)
|
|
10
18
|
from rasa.dialogue_understanding_test.du_test_result import (
|
|
11
19
|
DialogueUnderstandingTestResult,
|
|
12
20
|
)
|
|
21
|
+
from rasa.dialogue_understanding_test.test_case_simulation.test_case_tracker_simulator import ( # noqa: E501
|
|
22
|
+
TestCaseTrackerSimulator,
|
|
23
|
+
TestCaseTrackerSimulatorException,
|
|
24
|
+
TestCaseTrackerSimulatorResult,
|
|
25
|
+
)
|
|
26
|
+
from rasa.dialogue_understanding_test.utils import filter_metadata
|
|
13
27
|
from rasa.e2e_test.e2e_test_case import (
|
|
14
28
|
KEY_STUB_CUSTOM_ACTIONS,
|
|
15
|
-
ActualStepOutput,
|
|
16
|
-
TestStep,
|
|
17
29
|
Fixture,
|
|
18
30
|
Metadata,
|
|
19
31
|
)
|
|
20
32
|
from rasa.e2e_test.e2e_test_runner import E2ETestRunner
|
|
33
|
+
from rasa.shared.core.events import UserUttered
|
|
34
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
35
|
+
from rasa.shared.nlu.constants import PREDICTED_COMMANDS, PROMPTS
|
|
21
36
|
from rasa.utils.endpoints import EndpointConfig
|
|
22
37
|
|
|
23
38
|
structlogger = structlog.get_logger()
|
|
24
39
|
|
|
25
|
-
TEST_TURNS_TYPE = Dict[int, Union[TestStep, ActualStepOutput]]
|
|
26
|
-
|
|
27
40
|
|
|
28
41
|
class DialogueUnderstandingTestRunner:
|
|
29
|
-
"""Dialogue Understanding test suite runner.
|
|
42
|
+
"""Dialogue Understanding test suite runner.
|
|
43
|
+
|
|
44
|
+
Responsible for executing dialogue understanding test cases by simulating
|
|
45
|
+
conversations and validating expected outputs against actual responses.
|
|
46
|
+
|
|
47
|
+
Attributes:
|
|
48
|
+
agent: The Rasa agent instance used for processing messages
|
|
49
|
+
"""
|
|
30
50
|
|
|
31
51
|
def __init__(
|
|
32
52
|
self,
|
|
@@ -62,7 +82,8 @@ class DialogueUnderstandingTestRunner:
|
|
|
62
82
|
"load the trained model."
|
|
63
83
|
)
|
|
64
84
|
|
|
65
|
-
|
|
85
|
+
@staticmethod
|
|
86
|
+
def _check_action_server(endpoints: AvailableEndpoints) -> None:
|
|
66
87
|
"""Check if the action server is reachable."""
|
|
67
88
|
are_custom_actions_stubbed = (
|
|
68
89
|
endpoints
|
|
@@ -74,7 +95,7 @@ class DialogueUnderstandingTestRunner:
|
|
|
74
95
|
endpoints, "dialogue_understanding_test_runner"
|
|
75
96
|
)
|
|
76
97
|
|
|
77
|
-
async def
|
|
98
|
+
async def run_test_cases(
|
|
78
99
|
self,
|
|
79
100
|
test_cases: List[DialogueUnderstandingTestCase],
|
|
80
101
|
fixtures: List[Fixture],
|
|
@@ -90,4 +111,212 @@ class DialogueUnderstandingTestRunner:
|
|
|
90
111
|
Returns:
|
|
91
112
|
List[DialogueUnderstandingTestResult]: List of test results.
|
|
92
113
|
"""
|
|
93
|
-
|
|
114
|
+
results = []
|
|
115
|
+
output_channel = CollectingOutputChannel()
|
|
116
|
+
|
|
117
|
+
structlogger.info("Starting dialogue understanding tests.")
|
|
118
|
+
|
|
119
|
+
for i in tqdm(range(len(test_cases))):
|
|
120
|
+
test_case = test_cases[i]
|
|
121
|
+
|
|
122
|
+
# set up the tracker by simulating the conversation
|
|
123
|
+
tracker_simulator = TestCaseTrackerSimulator(self.agent, test_case)
|
|
124
|
+
await tracker_simulator.initialize_tracker(fixtures)
|
|
125
|
+
try:
|
|
126
|
+
simulation_result = await tracker_simulator.simulate_test_case(metadata)
|
|
127
|
+
except TestCaseTrackerSimulatorException as e:
|
|
128
|
+
structlogger.error(
|
|
129
|
+
"Failed to simulate test case. Skipping test case.",
|
|
130
|
+
error=str(e),
|
|
131
|
+
)
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
# run the actual test case
|
|
135
|
+
test_result = await self.run_test_case(
|
|
136
|
+
test_case, metadata, simulation_result, output_channel
|
|
137
|
+
)
|
|
138
|
+
results.append(test_result)
|
|
139
|
+
|
|
140
|
+
structlogger.info("Finished dialogue understanding tests.")
|
|
141
|
+
|
|
142
|
+
return results
|
|
143
|
+
|
|
144
|
+
async def run_test_case(
|
|
145
|
+
self,
|
|
146
|
+
test_case: DialogueUnderstandingTestCase,
|
|
147
|
+
metadata: List[Metadata],
|
|
148
|
+
simulation_result: TestCaseTrackerSimulatorResult,
|
|
149
|
+
output_channel: CollectingOutputChannel,
|
|
150
|
+
) -> DialogueUnderstandingTestResult:
|
|
151
|
+
"""Runs dialogue understanding test case.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
test_case: The test case to run.
|
|
155
|
+
metadata: List of metadata.
|
|
156
|
+
simulation_result: The test case tracker.
|
|
157
|
+
output_channel: The output channel.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
A dialogue understanding test result.
|
|
161
|
+
"""
|
|
162
|
+
test_passed = True
|
|
163
|
+
|
|
164
|
+
sender_id = simulation_result.sender_id
|
|
165
|
+
user_uttered_event_indices = simulation_result.user_uttered_event_indices
|
|
166
|
+
test_case_tracker = await self.agent.tracker_store.retrieve(sender_id)
|
|
167
|
+
|
|
168
|
+
for user_step_index, user_step in enumerate(
|
|
169
|
+
test_case.iterate_over_user_steps()
|
|
170
|
+
):
|
|
171
|
+
if user_step_index >= len(user_uttered_event_indices):
|
|
172
|
+
# the conversation could not be simulated completely and was
|
|
173
|
+
# stopped early, no further user messages can be evaluated
|
|
174
|
+
return DialogueUnderstandingTestResult(
|
|
175
|
+
test_case=test_case, passed=test_passed
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# create and save the tracker at the time just
|
|
179
|
+
# before the user message was sent
|
|
180
|
+
step_sender_id = f"{sender_id}_{user_step_index}"
|
|
181
|
+
await self._create_tracker_for_user_step(
|
|
182
|
+
step_sender_id,
|
|
183
|
+
test_case_tracker,
|
|
184
|
+
user_uttered_event_indices[user_step_index],
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# send the user message
|
|
188
|
+
try:
|
|
189
|
+
await self._send_user_message(
|
|
190
|
+
step_sender_id,
|
|
191
|
+
test_case,
|
|
192
|
+
user_step,
|
|
193
|
+
metadata,
|
|
194
|
+
output_channel=output_channel,
|
|
195
|
+
)
|
|
196
|
+
except Exception as e:
|
|
197
|
+
structlogger.error(
|
|
198
|
+
"dialogue_understanding_test_runner.send_user_message.failed",
|
|
199
|
+
test_case=test_case.full_name(),
|
|
200
|
+
user_message=user_step.text,
|
|
201
|
+
error=str(e),
|
|
202
|
+
)
|
|
203
|
+
# as sending the user message failed, we cannot continue with the test
|
|
204
|
+
# as subsequent user message do not match the actual conversation
|
|
205
|
+
# return a test result up until this point
|
|
206
|
+
return DialogueUnderstandingTestResult(
|
|
207
|
+
test_case=test_case, passed=test_passed
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# get the dialogue understanding output
|
|
211
|
+
tracker = await self.agent.tracker_store.retrieve(step_sender_id)
|
|
212
|
+
dialogue_understanding_output = self.get_dialogue_understanding_output(
|
|
213
|
+
tracker, user_uttered_event_indices[user_step_index]
|
|
214
|
+
)
|
|
215
|
+
user_step.dialogue_understanding_output = dialogue_understanding_output
|
|
216
|
+
|
|
217
|
+
# check if we have a command match
|
|
218
|
+
if not user_step.has_passed():
|
|
219
|
+
test_passed = False
|
|
220
|
+
|
|
221
|
+
return DialogueUnderstandingTestResult(test_case=test_case, passed=test_passed)
|
|
222
|
+
|
|
223
|
+
def get_dialogue_understanding_output(
|
|
224
|
+
self,
|
|
225
|
+
tracker: DialogueStateTracker,
|
|
226
|
+
index_user_uttered_event: int,
|
|
227
|
+
) -> Optional[DialogueUnderstandingOutput]:
|
|
228
|
+
"""Returns the dialogue understanding output.
|
|
229
|
+
|
|
230
|
+
Creates the dialogue understanding output from the commands and prompts
|
|
231
|
+
added to the user uttered event.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
tracker: The tracker for the current test step.
|
|
235
|
+
index_user_uttered_event: The index of the user uttered event.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
The dialogue understanding output with commands and optionally prompts.
|
|
239
|
+
"""
|
|
240
|
+
user_uttered_event = self._get_user_uttered_event_from_tracker(
|
|
241
|
+
tracker, index_user_uttered_event
|
|
242
|
+
)
|
|
243
|
+
if user_uttered_event is None:
|
|
244
|
+
return None
|
|
245
|
+
|
|
246
|
+
predicted_commands: Dict[str, Any] = user_uttered_event.parse_data.get( # type:ignore[assignment]
|
|
247
|
+
PREDICTED_COMMANDS, {}
|
|
248
|
+
)
|
|
249
|
+
# convert the predicted commands to Command objects
|
|
250
|
+
commands = {}
|
|
251
|
+
for component, list_of_commands in predicted_commands.items():
|
|
252
|
+
# remove any duplicate commands
|
|
253
|
+
commands[component] = list(
|
|
254
|
+
set(
|
|
255
|
+
[Command.command_from_json(command) for command in list_of_commands]
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
return DialogueUnderstandingOutput(
|
|
260
|
+
commands=commands,
|
|
261
|
+
prompts=user_uttered_event.parse_data.get(PROMPTS, []),
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
@staticmethod
|
|
265
|
+
def _get_user_uttered_event_from_tracker(
|
|
266
|
+
tracker: DialogueStateTracker,
|
|
267
|
+
index_user_uttered_event: int,
|
|
268
|
+
) -> Optional[UserUttered]:
|
|
269
|
+
"""Returns the user uttered event from the tracker at the given index."""
|
|
270
|
+
if (
|
|
271
|
+
tracker.events is None
|
|
272
|
+
or len(list(tracker.events)) <= index_user_uttered_event
|
|
273
|
+
):
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
user_uttered_event = list(tracker.events)[index_user_uttered_event]
|
|
277
|
+
|
|
278
|
+
if not user_uttered_event or not isinstance(user_uttered_event, UserUttered):
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
return user_uttered_event
|
|
282
|
+
|
|
283
|
+
async def _create_tracker_for_user_step(
|
|
284
|
+
self,
|
|
285
|
+
step_sender_id: str,
|
|
286
|
+
test_case_tracker: DialogueStateTracker,
|
|
287
|
+
index_user_uttered_event: int,
|
|
288
|
+
) -> None:
|
|
289
|
+
"""Creates a tracker for the user step."""
|
|
290
|
+
tracker = test_case_tracker.copy()
|
|
291
|
+
# modify the sender id so that the test case tracker is not overwritten
|
|
292
|
+
tracker.sender_id = step_sender_id
|
|
293
|
+
|
|
294
|
+
if tracker.events:
|
|
295
|
+
# get timestamp of the event just before the user uttered event
|
|
296
|
+
timestamp = tracker.events[index_user_uttered_event - 1].timestamp
|
|
297
|
+
# revert the tracker to the event just before the user uttered event
|
|
298
|
+
tracker = tracker.travel_back_in_time(timestamp)
|
|
299
|
+
|
|
300
|
+
# store the tracker with the unique sender id
|
|
301
|
+
await self.agent.tracker_store.save(tracker)
|
|
302
|
+
|
|
303
|
+
async def _send_user_message(
|
|
304
|
+
self,
|
|
305
|
+
sender_id: str,
|
|
306
|
+
test_case: DialogueUnderstandingTestCase,
|
|
307
|
+
user_step: DialogueUnderstandingTestStep,
|
|
308
|
+
metadata: List[Metadata],
|
|
309
|
+
output_channel: CollectingOutputChannel = CollectingOutputChannel(),
|
|
310
|
+
) -> None:
|
|
311
|
+
"""Sends a user message to the agent."""
|
|
312
|
+
metadata_for_step = filter_metadata(test_case, user_step, metadata, sender_id)
|
|
313
|
+
|
|
314
|
+
user_message = UserMessage(
|
|
315
|
+
user_step.text,
|
|
316
|
+
output_channel,
|
|
317
|
+
sender_id,
|
|
318
|
+
metadata=metadata_for_step,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
with set_record_commands_and_prompts():
|
|
322
|
+
await self.agent.handle_message(user_message)
|