rasa-pro 3.11.5__py3-none-any.whl → 3.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- README.md +10 -13
- 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 +17 -11
- rasa/anonymization/anonymization_rule_orchestrator.py +2 -3
- rasa/cli/arguments/data.py +2 -2
- rasa/cli/arguments/default_arguments.py +1 -1
- 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 +20 -3
- rasa/cli/dialogue_understanding_test.py +386 -0
- rasa/cli/evaluate.py +1 -1
- rasa/cli/export.py +6 -6
- rasa/cli/inspect.py +20 -1
- rasa/cli/interactive.py +4 -5
- rasa/cli/llm_fine_tuning.py +51 -16
- rasa/cli/markers.py +1 -2
- rasa/cli/project_templates/calm/actions/add_contact.py +1 -1
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +1 -2
- rasa/cli/project_templates/calm/domain/remove_contact.yml +1 -2
- rasa/cli/project_templates/calm/domain/shared.yml +1 -4
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/project_templates/tutorial/actions/actions.py +3 -2
- rasa/cli/shell.py +5 -6
- 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/train.py +3 -0
- rasa/cli/utils.py +25 -5
- rasa/constants.py +0 -1
- rasa/core/__init__.py +0 -1
- rasa/core/actions/action.py +135 -208
- rasa/core/actions/action_handle_digressions.py +164 -0
- 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 +18 -6
- 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/custom_action_executor.py +1 -1
- rasa/core/actions/direct_custom_actions_executor.py +1 -0
- rasa/core/actions/forms.py +22 -15
- 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 +7 -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 +80 -24
- rasa/core/channels/facebook.py +5 -5
- rasa/core/channels/hangouts.py +7 -8
- rasa/core/channels/inspector/dist/assets/{arc-f0f8bd46.js → arc-9f1365dc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7162c77d.js → blockDiagram-38ab4fdb-e0f81b12.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-b1d0d098.js → c4Diagram-3d4e48cf-9deaee1c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-44956714.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-807a1b27.js → classDiagram-70f12bd4-20450a96.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-5238dcdb.js → classDiagram-v2-f2320105-749d2abf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-a9475142.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-75dfaa67.js → createText-2e5e7dd3-bef0b38c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-df20501d.js → edges-e0da2a9e-943801a7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-13cf4797.js → erDiagram-9861fffd-d523a948.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-a4991264.js → flowDb-956e92f1-54e4cf19.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-ccecf773.js → flowDiagram-66a62f08-48bfbbe8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-43fa749a.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b5801783.js → flowchart-elk-definition-4a651766-17c30827.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-161e079a.js → ganttDiagram-c361ad54-43086f2d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-f38e86a4.js → gitGraphDiagram-72cf32ee-5c8b693e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-be6ef5d8.js → graph-41a90d26.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-d9ce8994.js → index-3862675e-b43eeae9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-7794b245.js → index-e8affe45.js} +155 -155
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-5000a3dc.js → infoDiagram-f8f76790-0b20676b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-8ef0a17a.js → journeyDiagram-49397b02-39bce7b5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-d649bc98.js → layout-dc8eeea4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-95add810.js → line-c4d2e756.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-f6025094.js → linear-86f6f2d9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-2e8531c4.js → mindmap-definition-fc14e90a-4216f771.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-918adfdb.js → pieDiagram-8a3498a8-1a0cfa96.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-cbd01797.js → quadrantDiagram-120e2f19-f91e67cf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-6a8b877b.js → requirementDiagram-deff3bca-d4046bed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-c377c3fe.js → sankeyDiagram-04a897e0-2cf6d1d7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-ab9e9b7f.js → sequenceDiagram-704730f1-751ac4f5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-5e6ae67d.js → stateDiagram-587899a1-f734f4d4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-40643476.js → stateDiagram-v2-d93cdb3a-91c65710.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-afb8d108.js → styles-6aaf32cf-e0cff7be.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-7edc9423.js → styles-9a916d00-c8029e5d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-c1d8f7e9.js → styles-c10674c1-114f312a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f494b2ef.js → svgDrawCommon-08f97a94-b7b9dc00.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-11c7cdd0.js → timeline-definition-85554ec2-9536d189.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-3f191ec1.js → xychartDiagram-e933f94c-bf3b0f36.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +1 -0
- rasa/core/channels/inspector/src/App.tsx +15 -2
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +31 -0
- rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +68 -0
- rasa/core/channels/inspector/src/components/Welcome.tsx +19 -13
- rasa/core/channels/inspector/yarn.lock +5 -0
- 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 +8 -28
- rasa/core/channels/studio_chat.py +212 -0
- rasa/core/channels/telegram.py +105 -55
- rasa/core/channels/twilio.py +3 -3
- rasa/core/channels/vier_cvg.py +2 -2
- rasa/core/channels/voice_ready/audiocodes.py +9 -9
- 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 +2 -2
- rasa/core/channels/voice_stream/asr/asr_engine.py +12 -6
- rasa/core/channels/voice_stream/asr/asr_event.py +5 -0
- rasa/core/channels/voice_stream/asr/azure.py +16 -3
- rasa/core/channels/voice_stream/asr/deepgram.py +76 -19
- rasa/core/channels/voice_stream/audiocodes.py +292 -0
- rasa/core/channels/voice_stream/browser_audio.py +14 -7
- rasa/core/channels/voice_stream/call_state.py +6 -2
- rasa/core/channels/voice_stream/genesys.py +320 -0
- rasa/core/channels/voice_stream/tts/azure.py +13 -5
- rasa/core/channels/voice_stream/tts/cartesia.py +34 -14
- 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 +12 -8
- rasa/core/channels/voice_stream/util.py +1 -1
- rasa/core/channels/voice_stream/voice_channel.py +100 -56
- rasa/core/channels/webexteams.py +3 -4
- rasa/core/constants.py +2 -0
- 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 +12 -9
- rasa/core/nlg/__init__.py +1 -1
- rasa/core/nlg/callback.py +2 -3
- rasa/core/nlg/contextual_response_rephraser.py +82 -14
- rasa/core/nlg/generator.py +85 -17
- rasa/core/nlg/interpolator.py +4 -3
- rasa/core/nlg/response.py +9 -7
- rasa/core/nlg/summarize.py +1 -0
- rasa/core/nlg/translate.py +55 -0
- rasa/core/persistor.py +3 -3
- rasa/core/policies/ensemble.py +10 -9
- rasa/core/policies/enterprise_search_policy.py +87 -21
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flow_policy.py +13 -14
- rasa/core/policies/flows/flow_executor.py +85 -55
- 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 +167 -74
- rasa/core/run.py +5 -4
- 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 +138 -49
- 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 +38 -1
- rasa/dialogue_understanding/commands/cancel_flow_command.py +96 -9
- rasa/dialogue_understanding/commands/change_flow_command.py +36 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +36 -4
- rasa/dialogue_understanding/commands/clarify_command.py +46 -4
- rasa/dialogue_understanding/commands/command.py +3 -2
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +14 -5
- 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/handle_digressions_command.py +144 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +34 -4
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +36 -4
- rasa/dialogue_understanding/commands/noop_command.py +2 -1
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +34 -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 +55 -16
- rasa/dialogue_understanding/commands/skip_question_command.py +34 -4
- rasa/dialogue_understanding/commands/start_flow_command.py +78 -2
- rasa/dialogue_understanding/commands/user_silence_command.py +3 -5
- rasa/dialogue_understanding/commands/utils.py +126 -43
- rasa/dialogue_understanding/constants.py +2 -0
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_generator.py +120 -79
- rasa/dialogue_understanding/generator/command_parser.py +245 -0
- rasa/dialogue_understanding/generator/constants.py +12 -4
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -7
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +187 -59
- rasa/dialogue_understanding/generator/llm_command_generator.py +6 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +106 -110
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +53 -11
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +58 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +57 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +574 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +41 -386
- rasa/dialogue_understanding/generator/utils.py +76 -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 +7 -4
- rasa/dialogue_understanding/patterns/completed.py +1 -1
- rasa/dialogue_understanding/patterns/continue_interrupted.py +1 -1
- rasa/dialogue_understanding/patterns/correction.py +17 -3
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +78 -2
- rasa/dialogue_understanding/patterns/handle_digressions.py +81 -0
- 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/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +193 -43
- 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 +56 -10
- rasa/dialogue_understanding/utils.py +164 -0
- rasa/dialogue_understanding_test/README.md +429 -0
- rasa/dialogue_understanding_test/__init__.py +0 -0
- rasa/dialogue_understanding_test/command_comparison.py +60 -0
- rasa/dialogue_understanding_test/command_metric_calculation.py +122 -0
- rasa/dialogue_understanding_test/constants.py +22 -0
- rasa/dialogue_understanding_test/du_test_case.py +448 -0
- rasa/dialogue_understanding_test/du_test_result.py +390 -0
- rasa/dialogue_understanding_test/du_test_runner.py +322 -0
- rasa/dialogue_understanding_test/du_test_schema.yml +161 -0
- rasa/dialogue_understanding_test/io.py +443 -0
- 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 +77 -0
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -1
- rasa/e2e_test/assertions.py +202 -175
- rasa/e2e_test/assertions_schema.yml +6 -0
- rasa/e2e_test/constants.py +16 -1
- rasa/e2e_test/e2e_config.py +102 -41
- rasa/e2e_test/e2e_config_schema.yml +28 -10
- rasa/e2e_test/e2e_test_case.py +5 -5
- 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 +143 -38
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +93 -0
- rasa/e2e_test/llm_judge_prompts/groundedness_prompt_template.jinja2 +169 -0
- rasa/e2e_test/stub_custom_action.py +1 -1
- rasa/e2e_test/utils/generative_assertions.py +243 -0
- rasa/e2e_test/utils/io.py +123 -93
- rasa/e2e_test/utils/validation.py +101 -3
- rasa/engine/caching.py +5 -7
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +3 -2
- rasa/engine/language.py +182 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_components.py +13 -15
- rasa/engine/recipes/default_recipe.py +65 -49
- rasa/engine/recipes/graph_recipe.py +10 -7
- 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 +6 -4
- rasa/engine/storage/resource.py +2 -1
- rasa/engine/storage/storage.py +8 -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 +36 -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 +19 -14
- rasa/jupyter.py +2 -2
- rasa/llm_fine_tuning/annotation_module.py +4 -4
- rasa/llm_fine_tuning/conversations.py +5 -33
- rasa/llm_fine_tuning/llm_data_preparation_module.py +6 -4
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -4
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +18 -13
- rasa/llm_fine_tuning/paraphrasing_module.py +6 -2
- rasa/llm_fine_tuning/storage.py +3 -3
- rasa/llm_fine_tuning/train_test_split_module.py +27 -27
- rasa/llm_fine_tuning/utils.py +7 -0
- 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 +13 -10
- rasa/model_manager/socket_bridge.py +15 -9
- 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 -9
- rasa/model_service.py +5 -6
- rasa/model_testing.py +13 -15
- rasa/model_training.py +29 -29
- rasa/nlu/classifiers/diet_classifier.py +72 -73
- rasa/nlu/classifiers/fallback_classifier.py +9 -8
- 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 +3 -2
- rasa/shared/constants.py +45 -18
- rasa/shared/core/command_payload_reader.py +15 -7
- rasa/shared/core/constants.py +34 -4
- rasa/shared/core/conversation.py +1 -2
- rasa/shared/core/domain.py +19 -20
- rasa/shared/core/events.py +60 -39
- rasa/shared/core/flows/__init__.py +0 -1
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +107 -26
- rasa/shared/core/flows/flow_step.py +4 -3
- rasa/shared/core/flows/flow_step_links.py +1 -2
- rasa/shared/core/flows/flow_step_sequence.py +1 -1
- rasa/shared/core/flows/flows_list.py +3 -3
- rasa/shared/core/flows/flows_yaml_schema.json +69 -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 +1 -1
- rasa/shared/core/flows/steps/call.py +1 -1
- rasa/shared/core/flows/steps/collect.py +22 -40
- rasa/shared/core/flows/steps/internal.py +1 -1
- rasa/shared/core/flows/steps/link.py +1 -1
- rasa/shared/core/flows/steps/no_operation.py +2 -2
- rasa/shared/core/flows/steps/set_slots.py +1 -1
- rasa/shared/core/flows/utils.py +44 -4
- rasa/shared/core/flows/validation.py +4 -6
- rasa/shared/core/generator.py +20 -21
- rasa/shared/core/slot_mappings.py +360 -121
- rasa/shared/core/slots.py +163 -6
- rasa/shared/core/trackers.py +108 -33
- 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/importer.py +58 -2
- rasa/shared/importers/rasa.py +5 -6
- rasa/shared/importers/utils.py +1 -1
- rasa/shared/nlu/constants.py +9 -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 +19 -11
- 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_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +150 -15
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +9 -7
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +13 -11
- rasa/shared/providers/_configs/litellm_router_client_config.py +12 -10
- rasa/shared/providers/_configs/model_group_config.py +8 -5
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +14 -12
- rasa/shared/providers/_configs/rasa_llm_client_config.py +5 -3
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +12 -11
- 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/constants.py +6 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -1
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +32 -7
- rasa/shared/providers/embedding/embedding_client.py +1 -1
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +5 -2
- rasa/shared/providers/llm/_base_litellm_client.py +43 -18
- rasa/shared/providers/llm/azure_openai_llm_client.py +90 -34
- rasa/shared/providers/llm/default_litellm_llm_client.py +4 -2
- rasa/shared/providers/llm/litellm_router_llm_client.py +32 -9
- rasa/shared/providers/llm/llm_client.py +24 -8
- rasa/shared/providers/llm/llm_response.py +61 -2
- rasa/shared/providers/llm/openai_llm_client.py +11 -5
- rasa/shared/providers/llm/rasa_llm_client.py +17 -14
- rasa/shared/providers/llm/self_hosted_llm_client.py +35 -15
- rasa/shared/providers/mappings.py +18 -19
- rasa/shared/providers/router/_base_litellm_router_client.py +48 -15
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/cli.py +1 -1
- rasa/shared/utils/common.py +15 -1
- rasa/shared/utils/constants.py +3 -0
- 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 +100 -18
- rasa/shared/utils/pykwalify_extensions.py +25 -1
- rasa/shared/utils/schemas/domain.yml +26 -1
- rasa/shared/utils/schemas/events.py +1 -1
- rasa/shared/utils/yaml.py +24 -20
- 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 +21 -5
- rasa/telemetry.py +127 -48
- rasa/tracing/config.py +5 -3
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/attribute_extractors.py +92 -14
- rasa/tracing/instrumentation/instrumentation.py +61 -5
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +1 -1
- rasa/tracing/instrumentation/metrics.py +52 -11
- rasa/tracing/metric_instrument_provider.py +54 -14
- rasa/utils/common.py +12 -24
- 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 +594 -115
- rasa/version.py +1 -1
- {rasa_pro-3.11.5.dist-info → rasa_pro-3.12.0.dist-info}/METADATA +23 -26
- rasa_pro-3.12.0.dist-info/RECORD +829 -0
- rasa/core/channels/inspector/dist/assets/channel-e265ea59.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-21f8a43d.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-5c8ce12d.js +0 -1
- rasa_pro-3.11.5.dist-info/RECORD +0 -785
- /rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +0 -0
- {rasa_pro-3.11.5.dist-info → rasa_pro-3.12.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.11.5.dist-info → rasa_pro-3.12.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.11.5.dist-info → rasa_pro-3.12.0.dist-info}/entry_points.txt +0 -0
rasa/e2e_test/e2e_config.py
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import dataclasses
|
|
4
|
-
from dataclasses import dataclass
|
|
5
3
|
from pathlib import Path
|
|
6
|
-
from typing import Generator, Optional,
|
|
4
|
+
from typing import Any, Dict, Generator, Optional, Tuple
|
|
7
5
|
|
|
8
6
|
import structlog
|
|
9
|
-
from pydantic import BaseModel
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
10
8
|
|
|
11
9
|
from rasa.e2e_test.constants import (
|
|
10
|
+
DEFAULT_E2E_TESTING_MODEL,
|
|
12
11
|
E2E_CONFIG_SCHEMA_FILE_PATH,
|
|
13
|
-
|
|
12
|
+
KEY_EXTRA_PARAMETERS,
|
|
14
13
|
KEY_LLM_E2E_TEST_CONVERSION,
|
|
14
|
+
KEY_LLM_JUDGE,
|
|
15
15
|
)
|
|
16
16
|
from rasa.shared.constants import (
|
|
17
17
|
API_BASE_CONFIG_KEY,
|
|
18
18
|
DEPLOYMENT_CONFIG_KEY,
|
|
19
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
19
20
|
MODEL_CONFIG_KEY,
|
|
21
|
+
MODELS_CONFIG_KEY,
|
|
20
22
|
OPENAI_PROVIDER,
|
|
21
23
|
PROVIDER_CONFIG_KEY,
|
|
22
24
|
)
|
|
23
|
-
from rasa.shared.
|
|
25
|
+
from rasa.shared.utils.llm import (
|
|
26
|
+
combine_custom_and_default_config,
|
|
27
|
+
resolve_model_client_config,
|
|
28
|
+
)
|
|
24
29
|
from rasa.shared.utils.yaml import (
|
|
25
30
|
parse_raw_yaml,
|
|
26
31
|
read_schema_file,
|
|
@@ -32,42 +37,103 @@ structlogger = structlog.get_logger()
|
|
|
32
37
|
CONFTEST_PATTERNS = ["conftest.yml", "conftest.yaml"]
|
|
33
38
|
|
|
34
39
|
|
|
35
|
-
class
|
|
36
|
-
"""
|
|
40
|
+
class BaseModelConfig(BaseModel):
|
|
41
|
+
"""Base class for model configurations used by generative assertions."""
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
provider: Optional[str] = None
|
|
44
|
+
model: Optional[str] = None
|
|
45
|
+
extra_parameters: Dict[str, Any] = Field(default_factory=dict)
|
|
46
|
+
model_group: Optional[str] = None
|
|
41
47
|
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"""Class for storing the configuration of the LLM-As-Judge.
|
|
49
|
+
class LLMJudgeConfig(BaseModel):
|
|
50
|
+
"""Class for storing the configuration of the LLM-Judge.
|
|
46
51
|
|
|
47
|
-
The LLM-
|
|
52
|
+
The LLM-Judge is used to measure the factual correctness
|
|
48
53
|
(i.e., how grounded in the source documents the response is),
|
|
49
54
|
or relevance of the generated response during E2E testing.
|
|
50
55
|
"""
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
llm_config: BaseModelConfig
|
|
58
|
+
embeddings: Optional[BaseModelConfig] = None
|
|
54
59
|
|
|
55
|
-
@
|
|
56
|
-
def
|
|
60
|
+
@classmethod
|
|
61
|
+
def get_default_llm_config(cls) -> Dict[str, Any]:
|
|
62
|
+
return {
|
|
63
|
+
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
64
|
+
MODEL_CONFIG_KEY: DEFAULT_E2E_TESTING_MODEL,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def from_dict(cls, config_data: Dict[str, Any]) -> LLMJudgeConfig:
|
|
57
69
|
"""Loads the configuration from a dictionary."""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
embeddings = config_data.pop(EMBEDDINGS_CONFIG_KEY, None)
|
|
71
|
+
llm_config = config_data.pop("llm", {})
|
|
72
|
+
|
|
73
|
+
llm_config = resolve_model_client_config(llm_config)
|
|
74
|
+
llm_config, extra_parameters = cls.extract_attributes(llm_config)
|
|
75
|
+
llm_config = combine_custom_and_default_config(
|
|
76
|
+
llm_config, cls.get_default_llm_config()
|
|
77
|
+
)
|
|
78
|
+
embeddings_config = resolve_model_client_config(embeddings)
|
|
63
79
|
|
|
64
|
-
return LLMJudgeConfig(
|
|
80
|
+
return LLMJudgeConfig(
|
|
81
|
+
llm_config=BaseModelConfig(extra_parameters=extra_parameters, **llm_config),
|
|
82
|
+
embeddings=BaseModelConfig(**embeddings_config)
|
|
83
|
+
if embeddings_config
|
|
84
|
+
else None,
|
|
85
|
+
)
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
@classmethod
|
|
88
|
+
def extract_attributes(
|
|
89
|
+
cls, llm_config: Dict[str, Any]
|
|
90
|
+
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
91
|
+
"""Extract the expected fields from the configuration."""
|
|
92
|
+
required_config = {}
|
|
93
|
+
|
|
94
|
+
expected_fields = [
|
|
95
|
+
PROVIDER_CONFIG_KEY,
|
|
96
|
+
MODEL_CONFIG_KEY,
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
if PROVIDER_CONFIG_KEY in llm_config:
|
|
100
|
+
required_config = {
|
|
101
|
+
expected_field: llm_config.pop(expected_field, None)
|
|
102
|
+
for expected_field in expected_fields
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
elif MODELS_CONFIG_KEY in llm_config:
|
|
106
|
+
llm_config = llm_config.pop(MODELS_CONFIG_KEY)[0]
|
|
107
|
+
|
|
108
|
+
required_config = {
|
|
109
|
+
expected_field: llm_config.pop(expected_field, None)
|
|
110
|
+
for expected_field in expected_fields
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
clean_config = clean_up_config(required_config)
|
|
114
|
+
return clean_config, llm_config
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def llm_config_as_dict(self) -> Dict[str, Any]:
|
|
118
|
+
return extract_config(self.llm_config)
|
|
68
119
|
|
|
69
|
-
|
|
70
|
-
|
|
120
|
+
@property
|
|
121
|
+
def embeddings_config_as_dict(self) -> Dict[str, Any]:
|
|
122
|
+
if self.embeddings is None:
|
|
123
|
+
return {}
|
|
124
|
+
|
|
125
|
+
return extract_config(self.embeddings)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def clean_up_config(config_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
129
|
+
"""Remove None values from the configuration."""
|
|
130
|
+
return {key: value for key, value in config_data.items() if value}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def extract_config(config: BaseModelConfig) -> Dict[str, Any]:
|
|
134
|
+
clean_config = clean_up_config(dict(config))
|
|
135
|
+
extra_parameters = clean_config.pop(KEY_EXTRA_PARAMETERS, {})
|
|
136
|
+
return {**clean_config, **extra_parameters}
|
|
71
137
|
|
|
72
138
|
|
|
73
139
|
class LLME2ETestConverterConfig(BaseModel):
|
|
@@ -99,7 +165,10 @@ class LLME2ETestConverterConfig(BaseModel):
|
|
|
99
165
|
|
|
100
166
|
@classmethod
|
|
101
167
|
def get_default_config(cls) -> Dict[str, Any]:
|
|
102
|
-
return {
|
|
168
|
+
return {
|
|
169
|
+
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
170
|
+
MODEL_CONFIG_KEY: DEFAULT_E2E_TESTING_MODEL,
|
|
171
|
+
}
|
|
103
172
|
|
|
104
173
|
@staticmethod
|
|
105
174
|
def _clean_up_config(config_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -160,24 +229,16 @@ def create_llm_judge_config(test_case_path: Optional[Path]) -> LLMJudgeConfig:
|
|
|
160
229
|
structlogger.debug("e2e_config.create_llm_judge_config.no_conftest_detected")
|
|
161
230
|
return LLMJudgeConfig.from_dict(config_data)
|
|
162
231
|
|
|
163
|
-
llm_judge_config_data = config_data.get(
|
|
232
|
+
llm_judge_config_data = config_data.get(KEY_LLM_JUDGE, {})
|
|
164
233
|
if not llm_judge_config_data:
|
|
165
|
-
structlogger.debug("e2e_config.create_llm_judge_config.
|
|
234
|
+
structlogger.debug("e2e_config.create_llm_judge_config.no_llm_judge_key")
|
|
166
235
|
|
|
167
236
|
structlogger.info(
|
|
168
237
|
"e2e_config.create_llm_judge_config.success",
|
|
169
238
|
llm_judge_config_data=llm_judge_config_data,
|
|
170
239
|
)
|
|
171
240
|
|
|
172
|
-
|
|
173
|
-
return LLMJudgeConfig.from_dict(llm_judge_config_data)
|
|
174
|
-
except InvalidLLMConfiguration as e:
|
|
175
|
-
structlogger.error(
|
|
176
|
-
"e2e_config.create_llm_judge_config.invalid_llm_configuration",
|
|
177
|
-
error_message=str(e),
|
|
178
|
-
event_info="Falling back to default configuration.",
|
|
179
|
-
)
|
|
180
|
-
return LLMJudgeConfig()
|
|
241
|
+
return LLMJudgeConfig.from_dict(llm_judge_config_data)
|
|
181
242
|
|
|
182
243
|
|
|
183
244
|
def create_llm_e2e_test_converter_config(
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
mapping:
|
|
2
|
-
|
|
2
|
+
llm_judge:
|
|
3
3
|
type: map
|
|
4
4
|
mapping:
|
|
5
|
-
|
|
6
|
-
type:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
llm:
|
|
6
|
+
type: map
|
|
7
|
+
allowempty: true
|
|
8
|
+
mapping:
|
|
9
|
+
provider:
|
|
10
|
+
type: str
|
|
11
|
+
nullable: false
|
|
12
|
+
model:
|
|
13
|
+
type: str
|
|
14
|
+
nullable: false
|
|
15
|
+
model_group:
|
|
16
|
+
type: str
|
|
17
|
+
nullable: false
|
|
18
|
+
embeddings:
|
|
19
|
+
type: map
|
|
20
|
+
allowempty: true
|
|
21
|
+
mapping:
|
|
22
|
+
provider:
|
|
23
|
+
type: str
|
|
24
|
+
nullable: false
|
|
25
|
+
model:
|
|
26
|
+
type: str
|
|
27
|
+
nullable: false
|
|
28
|
+
model_group:
|
|
29
|
+
type: str
|
|
30
|
+
nullable: false
|
|
13
31
|
llm_e2e_test_conversion:
|
|
14
32
|
type: map
|
|
15
33
|
mapping:
|
|
16
|
-
|
|
34
|
+
provider:
|
|
17
35
|
type: str
|
|
18
36
|
model:
|
|
19
37
|
type: str
|
rasa/e2e_test/e2e_test_case.py
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
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
|
|
|
6
5
|
import structlog
|
|
7
6
|
|
|
7
|
+
from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
|
|
8
8
|
from rasa.e2e_test.assertions import Assertion
|
|
9
9
|
from rasa.e2e_test.constants import (
|
|
10
|
-
KEY_ASSERTIONS,
|
|
11
10
|
KEY_ASSERTION_ORDER_ENABLED,
|
|
11
|
+
KEY_ASSERTIONS,
|
|
12
12
|
KEY_BOT_INPUT,
|
|
13
13
|
KEY_BOT_UTTERED,
|
|
14
14
|
KEY_FIXTURES,
|
|
15
15
|
KEY_METADATA,
|
|
16
|
-
KEY_STUB_CUSTOM_ACTIONS,
|
|
17
16
|
KEY_SLOT_NOT_SET,
|
|
18
17
|
KEY_SLOT_SET,
|
|
19
18
|
KEY_STEPS,
|
|
19
|
+
KEY_STUB_CUSTOM_ACTIONS,
|
|
20
20
|
KEY_TEST_CASE,
|
|
21
21
|
KEY_TEST_CASES,
|
|
22
22
|
KEY_USER_INPUT,
|
|
@@ -551,7 +551,7 @@ class Metadata:
|
|
|
551
551
|
class TestSuite:
|
|
552
552
|
"""Class for representing all top level test suite keys."""
|
|
553
553
|
|
|
554
|
-
test_cases: List[TestCase]
|
|
554
|
+
test_cases: List[Union[TestCase, DialogueUnderstandingTestCase]]
|
|
555
555
|
fixtures: List[Fixture]
|
|
556
556
|
metadata: List[Metadata]
|
|
557
557
|
stub_custom_actions: Dict[Text, StubCustomAction]
|
|
@@ -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
rasa/e2e_test/e2e_test_runner.py
CHANGED
|
@@ -5,7 +5,7 @@ import difflib
|
|
|
5
5
|
from asyncio import CancelledError
|
|
6
6
|
from collections import defaultdict
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any, DefaultDict, Dict, List, Optional, Text, Tuple, Union
|
|
8
|
+
from typing import Any, Callable, DefaultDict, Dict, List, Optional, Text, Tuple, Union
|
|
9
9
|
from urllib.parse import urlparse
|
|
10
10
|
|
|
11
11
|
import requests
|
|
@@ -18,6 +18,7 @@ from rasa.core.constants import ACTIVE_FLOW_METADATA_KEY, STEP_ID_METADATA_KEY
|
|
|
18
18
|
from rasa.core.exceptions import AgentNotReady
|
|
19
19
|
from rasa.core.persistor import StorageType
|
|
20
20
|
from rasa.core.utils import AvailableEndpoints
|
|
21
|
+
from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
|
|
21
22
|
from rasa.e2e_test.constants import TEST_CASE_NAME, TEST_FILE_NAME
|
|
22
23
|
from rasa.e2e_test.e2e_config import create_llm_judge_config
|
|
23
24
|
from rasa.e2e_test.e2e_test_case import (
|
|
@@ -123,11 +124,11 @@ class E2ETestRunner:
|
|
|
123
124
|
collector: Output channel.
|
|
124
125
|
steps: List of steps to run.
|
|
125
126
|
sender_id: The test case name with added timestamp suffix.
|
|
126
|
-
test_case_metadata: Metadata of test case.
|
|
127
|
+
test_case_metadata: Metadata of the test case.
|
|
127
128
|
input_metadata: List of metadata.
|
|
128
129
|
|
|
129
130
|
Returns:
|
|
130
|
-
Test turns: {turn_sequence (int)
|
|
131
|
+
Test turns: {turn_sequence (int): TestStep or ActualStepOutput}.
|
|
131
132
|
"""
|
|
132
133
|
turns: TEST_TURNS_TYPE = {}
|
|
133
134
|
event_cursor = 0
|
|
@@ -151,9 +152,23 @@ class E2ETestRunner:
|
|
|
151
152
|
event_cursor,
|
|
152
153
|
)
|
|
153
154
|
|
|
155
|
+
# This variable tracks the position of the last user step.
|
|
156
|
+
# We use it to determine from which turn onward we should check
|
|
157
|
+
# for failures in case of the fail-fast logic.
|
|
158
|
+
last_user_step_position = 0
|
|
154
159
|
for position, step in enumerate(steps):
|
|
155
160
|
if step.actor != "user":
|
|
156
161
|
turns[position] = step
|
|
162
|
+
|
|
163
|
+
# Check for failures after each bot step
|
|
164
|
+
try:
|
|
165
|
+
self.fail_fast_check(
|
|
166
|
+
test_turns=turns,
|
|
167
|
+
last_user_step_position=last_user_step_position,
|
|
168
|
+
)
|
|
169
|
+
except RasaException:
|
|
170
|
+
break
|
|
171
|
+
|
|
157
172
|
continue
|
|
158
173
|
elif not step.text:
|
|
159
174
|
rasa.shared.utils.io.raise_warning(
|
|
@@ -163,6 +178,8 @@ class E2ETestRunner:
|
|
|
163
178
|
UserWarning,
|
|
164
179
|
)
|
|
165
180
|
continue
|
|
181
|
+
# Update to the current position because we have a valid user step
|
|
182
|
+
last_user_step_position = position
|
|
166
183
|
|
|
167
184
|
metadata = test_case_metadata.metadata if test_case_metadata else {}
|
|
168
185
|
|
|
@@ -202,6 +219,26 @@ class E2ETestRunner:
|
|
|
202
219
|
)
|
|
203
220
|
return turns
|
|
204
221
|
|
|
222
|
+
def fail_fast_check(
|
|
223
|
+
self, test_turns: TEST_TURNS_TYPE, last_user_step_position: int
|
|
224
|
+
) -> None:
|
|
225
|
+
"""Checks whether there are any test failures in 'test_turns'.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
test_turns (TEST_TURNS_TYPE): The transcript of test cases and events.
|
|
229
|
+
last_user_step_position (int): The start position in the test turns.
|
|
230
|
+
|
|
231
|
+
Raises:
|
|
232
|
+
RasaException if a failure is found.
|
|
233
|
+
"""
|
|
234
|
+
failures_found = self.find_test_failures(
|
|
235
|
+
test_turns=test_turns,
|
|
236
|
+
test_case=None,
|
|
237
|
+
last_user_step_position=last_user_step_position,
|
|
238
|
+
)
|
|
239
|
+
if failures_found:
|
|
240
|
+
raise RasaException("Test failure found. Aborting early.")
|
|
241
|
+
|
|
205
242
|
@staticmethod
|
|
206
243
|
def merge_metadata(
|
|
207
244
|
sender_id: Text,
|
|
@@ -754,13 +791,15 @@ class E2ETestRunner:
|
|
|
754
791
|
def find_test_failures(
|
|
755
792
|
cls,
|
|
756
793
|
test_turns: TEST_TURNS_TYPE,
|
|
757
|
-
test_case: TestCase,
|
|
794
|
+
test_case: Optional[TestCase],
|
|
795
|
+
last_user_step_position: int = 0,
|
|
758
796
|
) -> List[Tuple[TestFailure, int]]:
|
|
759
797
|
"""Finds the test failures in the transcript.
|
|
760
798
|
|
|
761
799
|
Args:
|
|
762
|
-
test_turns: The transcript of test cases and events.
|
|
763
|
-
test_case: The test case.
|
|
800
|
+
test_turns (TEST_TURNS_TYPE): The transcript of test cases and events.
|
|
801
|
+
test_case (Optional[TestCase]): The test case.
|
|
802
|
+
last_user_step_position (int): The start position in the test turns.
|
|
764
803
|
|
|
765
804
|
Returns:
|
|
766
805
|
The test failures or an empty list if there is no test failure.
|
|
@@ -769,9 +808,10 @@ class E2ETestRunner:
|
|
|
769
808
|
# with a user step
|
|
770
809
|
latest_response: ActualStepOutput = test_turns[-1] # type: ignore[assignment]
|
|
771
810
|
failures = []
|
|
772
|
-
position = 0
|
|
773
811
|
match = None
|
|
774
|
-
for position in range(len(test_turns) - 1):
|
|
812
|
+
for position in range(last_user_step_position, len(test_turns) - 1):
|
|
813
|
+
if position not in test_turns:
|
|
814
|
+
continue
|
|
775
815
|
turn_value = test_turns[position]
|
|
776
816
|
if isinstance(turn_value, ActualStepOutput):
|
|
777
817
|
latest_response = turn_value
|
|
@@ -924,19 +964,11 @@ class E2ETestRunner:
|
|
|
924
964
|
).name
|
|
925
965
|
self.agent.endpoints.action.kwargs[TEST_CASE_NAME] = test_case_name
|
|
926
966
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
sender_id, input_fixtures, input_metadata, test_case
|
|
967
|
+
sender_id = self.generate_sender_id(test_case.name)
|
|
968
|
+
_, test_result = await self._process_test_case(
|
|
969
|
+
test_case, sender_id, input_fixtures, input_metadata
|
|
931
970
|
)
|
|
932
971
|
|
|
933
|
-
if not test_case.uses_assertions():
|
|
934
|
-
test_result = self.generate_test_result(test_turns, test_case)
|
|
935
|
-
else:
|
|
936
|
-
test_result = await self.run_assertions(
|
|
937
|
-
sender_id, test_case, input_metadata
|
|
938
|
-
)
|
|
939
|
-
|
|
940
972
|
results.append(test_result)
|
|
941
973
|
|
|
942
974
|
coverage = kwargs.get("coverage", False)
|
|
@@ -983,6 +1015,32 @@ class E2ETestRunner:
|
|
|
983
1015
|
input_metadata,
|
|
984
1016
|
)
|
|
985
1017
|
|
|
1018
|
+
@staticmethod
|
|
1019
|
+
def generate_sender_id(test_case_name: str) -> str:
|
|
1020
|
+
# add timestamp suffix to ensure sender_id is unique
|
|
1021
|
+
return f"{test_case_name}_{datetime.datetime.now()}"
|
|
1022
|
+
|
|
1023
|
+
async def _process_test_case(
|
|
1024
|
+
self,
|
|
1025
|
+
test_case: TestCase,
|
|
1026
|
+
sender_id: str,
|
|
1027
|
+
input_fixtures: List[Fixture],
|
|
1028
|
+
input_metadata: Optional[List[Metadata]],
|
|
1029
|
+
) -> Tuple[TEST_TURNS_TYPE, TestResult]:
|
|
1030
|
+
"""Runs a single test case and returns the test turns and result."""
|
|
1031
|
+
test_turns = await self._run_test_case(
|
|
1032
|
+
sender_id, input_fixtures, input_metadata, test_case
|
|
1033
|
+
)
|
|
1034
|
+
|
|
1035
|
+
if not test_case.uses_assertions():
|
|
1036
|
+
test_result = self.generate_test_result(test_turns, test_case)
|
|
1037
|
+
else:
|
|
1038
|
+
test_result = await self.run_assertions(
|
|
1039
|
+
sender_id, test_case, input_metadata
|
|
1040
|
+
)
|
|
1041
|
+
|
|
1042
|
+
return test_turns, test_result
|
|
1043
|
+
|
|
986
1044
|
async def run_tests_for_fine_tuning(
|
|
987
1045
|
self,
|
|
988
1046
|
input_test_cases: List[TestCase],
|
|
@@ -1008,20 +1066,12 @@ class E2ETestRunner:
|
|
|
1008
1066
|
|
|
1009
1067
|
for i in tqdm(range(len(input_test_cases))):
|
|
1010
1068
|
test_case = input_test_cases[i]
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
test_turns = await self.
|
|
1014
|
-
sender_id, input_fixtures, input_metadata
|
|
1069
|
+
sender_id = self.generate_sender_id(test_case.name)
|
|
1070
|
+
|
|
1071
|
+
test_turns, test_result = await self._process_test_case(
|
|
1072
|
+
test_case, sender_id, input_fixtures, input_metadata
|
|
1015
1073
|
)
|
|
1016
1074
|
|
|
1017
|
-
# check if the e2e test is passing, only convert passing e2e tests into
|
|
1018
|
-
# conversations
|
|
1019
|
-
if not test_case.uses_assertions():
|
|
1020
|
-
test_result = self.generate_test_result(test_turns, test_case)
|
|
1021
|
-
else:
|
|
1022
|
-
test_result = await self.run_assertions(
|
|
1023
|
-
sender_id, test_case, input_metadata
|
|
1024
|
-
)
|
|
1025
1075
|
if not test_result.pass_status:
|
|
1026
1076
|
structlogger.warning(
|
|
1027
1077
|
"annotation_module.skip_test_case.failing_e2e_test",
|
|
@@ -1040,12 +1090,67 @@ class E2ETestRunner:
|
|
|
1040
1090
|
|
|
1041
1091
|
return conversations
|
|
1042
1092
|
|
|
1093
|
+
async def run_tests_to_convert_tests_to_du_tests(
|
|
1094
|
+
self,
|
|
1095
|
+
input_test_cases: List[TestCase],
|
|
1096
|
+
input_fixtures: List[Fixture],
|
|
1097
|
+
input_metadata: Optional[List[Metadata]],
|
|
1098
|
+
converting_method: Callable[
|
|
1099
|
+
[TEST_TURNS_TYPE, TestCase, bool, bool],
|
|
1100
|
+
Optional[DialogueUnderstandingTestCase],
|
|
1101
|
+
],
|
|
1102
|
+
) -> Tuple[
|
|
1103
|
+
List[DialogueUnderstandingTestCase], List[DialogueUnderstandingTestCase]
|
|
1104
|
+
]:
|
|
1105
|
+
"""Runs the test cases to convert them into dialogue understanding tests.
|
|
1106
|
+
|
|
1107
|
+
Converts test cases into dialogue understanding test cases.
|
|
1108
|
+
|
|
1109
|
+
Args:
|
|
1110
|
+
input_test_cases: Input test cases.
|
|
1111
|
+
input_fixtures: Input fixtures.
|
|
1112
|
+
input_metadata: Input metadata.
|
|
1113
|
+
converting_method: The method to convert the e2e test case into a
|
|
1114
|
+
dialogue understanding test case.
|
|
1115
|
+
|
|
1116
|
+
Returns:
|
|
1117
|
+
List of ready dialogue understanding test cases and list of
|
|
1118
|
+
dialogue understanding test cases to review.
|
|
1119
|
+
"""
|
|
1120
|
+
ready_du_test_cases = []
|
|
1121
|
+
to_review_du_test_cases = []
|
|
1122
|
+
|
|
1123
|
+
for i in tqdm(range(len(input_test_cases))):
|
|
1124
|
+
test_case = input_test_cases[i]
|
|
1125
|
+
sender_id = self.generate_sender_id(test_case.name)
|
|
1126
|
+
|
|
1127
|
+
test_turns, test_result = await self._process_test_case(
|
|
1128
|
+
test_case, sender_id, input_fixtures, input_metadata
|
|
1129
|
+
)
|
|
1130
|
+
|
|
1131
|
+
du_test_case = converting_method(
|
|
1132
|
+
test_turns,
|
|
1133
|
+
test_case,
|
|
1134
|
+
test_case.uses_assertions(),
|
|
1135
|
+
test_result.pass_status,
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
if du_test_case:
|
|
1139
|
+
if test_result.pass_status:
|
|
1140
|
+
ready_du_test_cases.append(du_test_case)
|
|
1141
|
+
else:
|
|
1142
|
+
to_review_du_test_cases.append(du_test_case)
|
|
1143
|
+
|
|
1144
|
+
return ready_du_test_cases, to_review_du_test_cases
|
|
1145
|
+
|
|
1043
1146
|
@staticmethod
|
|
1044
|
-
def _action_server_is_reachable(
|
|
1147
|
+
def _action_server_is_reachable(
|
|
1148
|
+
endpoints: AvailableEndpoints, module: str = "e2e_test_runner"
|
|
1149
|
+
) -> None:
|
|
1045
1150
|
"""Calls the action server health endpoint."""
|
|
1046
1151
|
if not endpoints.action:
|
|
1047
1152
|
structlogger.debug(
|
|
1048
|
-
"
|
|
1153
|
+
f"{module}._action_server_is_reachable",
|
|
1049
1154
|
message="No action endpoint configured. Skipping the health check "
|
|
1050
1155
|
"of the action server.",
|
|
1051
1156
|
)
|
|
@@ -1053,7 +1158,7 @@ class E2ETestRunner:
|
|
|
1053
1158
|
|
|
1054
1159
|
if endpoints.action.actions_module:
|
|
1055
1160
|
structlogger.debug(
|
|
1056
|
-
"
|
|
1161
|
+
f"{module}._action_server_is_reachable",
|
|
1057
1162
|
message="Rasa server is configured to run custom actions directly. "
|
|
1058
1163
|
"Skipping the health check of the action server.",
|
|
1059
1164
|
)
|
|
@@ -1061,14 +1166,14 @@ class E2ETestRunner:
|
|
|
1061
1166
|
|
|
1062
1167
|
if not endpoints.action.url:
|
|
1063
1168
|
structlogger.debug(
|
|
1064
|
-
"
|
|
1169
|
+
f"{module}._action_server_is_reachable",
|
|
1065
1170
|
message="Action endpoint URL is not defined in the endpoint "
|
|
1066
1171
|
"configuration.",
|
|
1067
1172
|
)
|
|
1068
1173
|
return
|
|
1069
1174
|
|
|
1070
1175
|
structlogger.debug(
|
|
1071
|
-
"
|
|
1176
|
+
f"{module}._action_server_is_reachable",
|
|
1072
1177
|
message="Detected action URL in the endpoint configuration.\n"
|
|
1073
1178
|
f"Action Server URL: {endpoints.action.url}\n"
|
|
1074
1179
|
"Sending a health request to the action endpoint.",
|
|
@@ -1084,7 +1189,7 @@ class E2ETestRunner:
|
|
|
1084
1189
|
"Actions server URL is defined in your endpoint configuration as "
|
|
1085
1190
|
f"'{endpoints.action.url}'.\n"
|
|
1086
1191
|
"Please make sure your action server is running and properly "
|
|
1087
|
-
"configured. Since running
|
|
1192
|
+
"configured. Since running tests without a action server may "
|
|
1088
1193
|
f"lead to unpredictable results.\n{error}"
|
|
1089
1194
|
)
|
|
1090
1195
|
|
|
@@ -1096,7 +1201,7 @@ class E2ETestRunner:
|
|
|
1096
1201
|
)
|
|
1097
1202
|
|
|
1098
1203
|
structlogger.debug(
|
|
1099
|
-
"
|
|
1204
|
+
f"{module}._action_server_is_reachable",
|
|
1100
1205
|
message="Action endpoint has responded successfully.\n"
|
|
1101
1206
|
f"Response message: {response.text}\n"
|
|
1102
1207
|
f"Response status code: {response.status_code}.",
|