rasa-pro 3.8.18__py3-none-any.whl → 3.9.15__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 +6 -42
- rasa/__main__.py +14 -9
- rasa/anonymization/anonymization_pipeline.py +0 -1
- rasa/anonymization/anonymization_rule_executor.py +3 -3
- rasa/anonymization/utils.py +4 -3
- rasa/api.py +2 -2
- rasa/cli/arguments/default_arguments.py +1 -1
- rasa/cli/arguments/run.py +2 -2
- rasa/cli/arguments/test.py +1 -1
- rasa/cli/arguments/train.py +10 -10
- rasa/cli/e2e_test.py +27 -7
- rasa/cli/export.py +0 -1
- rasa/cli/license.py +3 -3
- rasa/cli/project_templates/calm/actions/action_template.py +1 -1
- rasa/cli/project_templates/calm/config.yml +1 -1
- rasa/cli/project_templates/calm/credentials.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/add_contact.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/remove_contact.yml +1 -1
- rasa/cli/project_templates/calm/domain/add_contact.yml +8 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +3 -0
- rasa/cli/project_templates/calm/domain/remove_contact.yml +9 -2
- rasa/cli/project_templates/calm/domain/shared.yml +5 -0
- rasa/cli/project_templates/calm/endpoints.yml +4 -4
- rasa/cli/project_templates/default/actions/actions.py +1 -1
- rasa/cli/project_templates/default/config.yml +5 -5
- rasa/cli/project_templates/default/credentials.yml +1 -1
- rasa/cli/project_templates/default/endpoints.yml +4 -4
- rasa/cli/project_templates/default/tests/test_stories.yml +1 -1
- rasa/cli/project_templates/tutorial/config.yml +1 -1
- rasa/cli/project_templates/tutorial/credentials.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
- rasa/cli/project_templates/tutorial/domain.yml +4 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +6 -6
- rasa/cli/run.py +0 -1
- rasa/cli/scaffold.py +3 -2
- rasa/cli/studio/download.py +11 -0
- rasa/cli/studio/studio.py +180 -24
- rasa/cli/studio/upload.py +0 -8
- rasa/cli/telemetry.py +18 -6
- rasa/cli/utils.py +21 -10
- rasa/cli/x.py +3 -2
- rasa/constants.py +1 -1
- rasa/core/actions/action.py +90 -315
- rasa/core/actions/action_exceptions.py +24 -0
- rasa/core/actions/constants.py +3 -0
- rasa/core/actions/custom_action_executor.py +188 -0
- rasa/core/actions/forms.py +11 -7
- rasa/core/actions/grpc_custom_action_executor.py +251 -0
- rasa/core/actions/http_custom_action_executor.py +140 -0
- rasa/core/actions/loops.py +3 -0
- rasa/core/actions/two_stage_fallback.py +1 -1
- rasa/core/agent.py +2 -4
- rasa/core/brokers/pika.py +1 -2
- rasa/core/channels/audiocodes.py +1 -1
- rasa/core/channels/botframework.py +0 -1
- rasa/core/channels/callback.py +0 -1
- rasa/core/channels/console.py +6 -8
- rasa/core/channels/development_inspector.py +1 -1
- rasa/core/channels/facebook.py +0 -3
- rasa/core/channels/hangouts.py +0 -6
- rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
- rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
- rasa/core/channels/rest.py +36 -21
- rasa/core/channels/rocketchat.py +0 -1
- rasa/core/channels/socketio.py +1 -1
- rasa/core/channels/telegram.py +3 -3
- rasa/core/channels/webexteams.py +0 -1
- rasa/core/concurrent_lock_store.py +1 -1
- rasa/core/evaluation/marker_base.py +1 -3
- rasa/core/evaluation/marker_stats.py +1 -2
- rasa/core/featurizers/single_state_featurizer.py +3 -26
- rasa/core/featurizers/tracker_featurizers.py +18 -122
- rasa/core/information_retrieval/__init__.py +7 -0
- rasa/core/information_retrieval/faiss.py +9 -4
- rasa/core/information_retrieval/information_retrieval.py +64 -7
- rasa/core/information_retrieval/milvus.py +7 -14
- rasa/core/information_retrieval/qdrant.py +8 -15
- rasa/core/lock_store.py +0 -1
- rasa/core/migrate.py +1 -2
- rasa/core/nlg/callback.py +3 -4
- rasa/core/policies/enterprise_search_policy.py +86 -22
- rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
- rasa/core/policies/flows/flow_executor.py +104 -2
- rasa/core/policies/intentless_policy.py +7 -9
- rasa/core/policies/memoization.py +3 -3
- rasa/core/policies/policy.py +18 -9
- rasa/core/policies/rule_policy.py +8 -11
- rasa/core/policies/ted_policy.py +61 -88
- rasa/core/policies/unexpected_intent_policy.py +8 -17
- rasa/core/processor.py +136 -47
- rasa/core/run.py +41 -25
- rasa/core/secrets_manager/endpoints.py +2 -2
- rasa/core/secrets_manager/vault.py +6 -8
- rasa/core/test.py +3 -5
- rasa/core/tracker_store.py +49 -14
- rasa/core/train.py +1 -3
- rasa/core/training/interactive.py +9 -6
- rasa/core/utils.py +5 -10
- rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
- rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
- rasa/dialogue_understanding/commands/__init__.py +4 -0
- rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/clarify_command.py +9 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
- rasa/dialogue_understanding/commands/error_command.py +12 -0
- rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/noop_command.py +9 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +38 -3
- rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
- rasa/dialogue_understanding/generator/__init__.py +16 -1
- rasa/dialogue_understanding/generator/command_generator.py +92 -6
- rasa/dialogue_understanding/generator/constants.py +18 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
- rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
- rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
- rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
- rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +36 -31
- rasa/dialogue_understanding/processor/command_processor.py +112 -3
- rasa/e2e_test/constants.py +1 -0
- rasa/e2e_test/e2e_test_case.py +44 -0
- rasa/e2e_test/e2e_test_runner.py +114 -11
- rasa/e2e_test/e2e_test_schema.yml +18 -0
- rasa/engine/caching.py +0 -1
- rasa/engine/graph.py +18 -6
- rasa/engine/recipes/config_files/default_config.yml +3 -3
- rasa/engine/recipes/default_components.py +1 -1
- rasa/engine/recipes/default_recipe.py +4 -5
- rasa/engine/recipes/recipe.py +1 -1
- rasa/engine/runner/dask.py +3 -9
- rasa/engine/storage/local_model_storage.py +0 -2
- rasa/engine/validation.py +179 -145
- rasa/exceptions.py +2 -2
- rasa/graph_components/validators/default_recipe_validator.py +3 -5
- rasa/hooks.py +0 -1
- rasa/model.py +1 -1
- rasa/model_training.py +1 -0
- rasa/nlu/classifiers/diet_classifier.py +33 -52
- rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
- rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
- rasa/nlu/extractors/crf_entity_extractor.py +54 -97
- rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
- rasa/nlu/featurizers/featurizer.py +1 -1
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +18 -49
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +26 -64
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
- rasa/nlu/persistor.py +68 -26
- rasa/nlu/selectors/response_selector.py +7 -10
- rasa/nlu/test.py +0 -3
- rasa/nlu/utils/hugging_face/registry.py +1 -1
- rasa/nlu/utils/spacy_utils.py +1 -3
- rasa/server.py +22 -7
- rasa/shared/constants.py +12 -1
- rasa/shared/core/command_payload_reader.py +109 -0
- rasa/shared/core/constants.py +4 -5
- rasa/shared/core/domain.py +57 -56
- rasa/shared/core/events.py +4 -7
- rasa/shared/core/flows/flow.py +9 -0
- rasa/shared/core/flows/flows_list.py +12 -0
- rasa/shared/core/flows/steps/action.py +7 -2
- rasa/shared/core/generator.py +12 -11
- rasa/shared/core/slot_mappings.py +315 -24
- rasa/shared/core/slots.py +4 -2
- rasa/shared/core/trackers.py +32 -14
- rasa/shared/core/training_data/loading.py +0 -1
- rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
- rasa/shared/core/training_data/structures.py +1 -1
- rasa/shared/core/training_data/visualization.py +1 -1
- rasa/shared/data.py +58 -1
- rasa/shared/exceptions.py +36 -2
- rasa/shared/importers/importer.py +1 -2
- rasa/shared/importers/rasa.py +0 -1
- rasa/shared/nlu/constants.py +2 -0
- rasa/shared/nlu/training_data/entities_parser.py +1 -2
- rasa/shared/nlu/training_data/features.py +2 -120
- rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
- rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
- rasa/shared/nlu/training_data/message.py +13 -0
- rasa/shared/nlu/training_data/training_data.py +0 -2
- rasa/shared/providers/openai/session_handler.py +2 -2
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/io.py +11 -1
- rasa/shared/utils/llm.py +1 -2
- rasa/shared/utils/pykwalify_extensions.py +1 -0
- rasa/shared/utils/schemas/domain.yml +3 -0
- rasa/shared/utils/yaml.py +44 -35
- rasa/studio/auth.py +26 -10
- rasa/studio/constants.py +2 -0
- rasa/studio/data_handler.py +114 -107
- rasa/studio/download.py +160 -27
- rasa/studio/results_logger.py +137 -0
- rasa/studio/train.py +6 -7
- rasa/studio/upload.py +159 -134
- rasa/telemetry.py +188 -34
- rasa/tracing/config.py +18 -3
- rasa/tracing/constants.py +26 -2
- rasa/tracing/instrumentation/attribute_extractors.py +50 -41
- rasa/tracing/instrumentation/instrumentation.py +290 -44
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
- rasa/tracing/instrumentation/metrics.py +109 -21
- rasa/tracing/metric_instrument_provider.py +83 -3
- rasa/utils/cli.py +2 -1
- rasa/utils/common.py +1 -1
- rasa/utils/endpoints.py +1 -2
- rasa/utils/io.py +72 -6
- rasa/utils/licensing.py +246 -31
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/tensorflow/data_generator.py +1 -1
- rasa/utils/tensorflow/environment.py +1 -1
- rasa/utils/tensorflow/model_data.py +201 -12
- rasa/utils/tensorflow/model_data_utils.py +499 -500
- rasa/utils/tensorflow/models.py +5 -6
- rasa/utils/tensorflow/rasa_layers.py +15 -15
- rasa/utils/train_utils.py +1 -1
- rasa/utils/url_tools.py +53 -0
- rasa/validator.py +305 -3
- rasa/version.py +1 -1
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/METADATA +25 -61
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/RECORD +276 -259
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
- rasa/utils/tensorflow/feature_array.py +0 -370
- /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/NOTICE +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/WHEEL +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/entry_points.txt +0 -0
|
@@ -16,6 +16,7 @@ from rasa.dialogue_understanding.commands import (
|
|
|
16
16
|
from rasa.dialogue_understanding.commands.handle_code_change_command import (
|
|
17
17
|
HandleCodeChangeCommand,
|
|
18
18
|
)
|
|
19
|
+
from rasa.dialogue_understanding.commands.set_slot_command import SetSlotExtractor
|
|
19
20
|
from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
20
21
|
from rasa.dialogue_understanding.patterns.collect_information import (
|
|
21
22
|
CollectInformationPatternFlowStackFrame,
|
|
@@ -36,16 +37,23 @@ from rasa.shared.constants import (
|
|
|
36
37
|
ROUTE_TO_CALM_SLOT,
|
|
37
38
|
RASA_PATTERN_CANNOT_HANDLE_CHITCHAT,
|
|
38
39
|
)
|
|
39
|
-
from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT
|
|
40
|
+
from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT, SlotMappingType
|
|
40
41
|
from rasa.shared.core.constants import FLOW_HASHES_SLOT
|
|
41
42
|
from rasa.shared.core.events import Event, SlotSet
|
|
42
43
|
from rasa.shared.core.flows import FlowsList
|
|
43
44
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
45
|
+
from rasa.shared.core.slots import Slot
|
|
44
46
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
45
47
|
from rasa.shared.nlu.constants import COMMANDS
|
|
46
48
|
|
|
47
49
|
structlogger = structlog.get_logger()
|
|
48
50
|
|
|
51
|
+
CANNOT_HANDLE_REASON = (
|
|
52
|
+
"A command generator attempted to set a slot "
|
|
53
|
+
"with a value extracted by an extractor "
|
|
54
|
+
"that is incompatible with the slot mapping type."
|
|
55
|
+
)
|
|
56
|
+
|
|
49
57
|
|
|
50
58
|
def contains_command(commands: List[Command], typ: Type[Command]) -> bool:
|
|
51
59
|
"""Check if a list of commands contains a command of a given type.
|
|
@@ -118,7 +126,7 @@ def validate_state_of_commands(commands: List[Command]) -> None:
|
|
|
118
126
|
]
|
|
119
127
|
if free_form_answer_commands != commands[: len(free_form_answer_commands)]:
|
|
120
128
|
structlogger.error(
|
|
121
|
-
"command_processor.validate_state_of_commands.free_form_answer_commands_not_at_beginning",
|
|
129
|
+
"command_processor.validate_state_of_commands.free_form_answer_commands_not_at_beginning",
|
|
122
130
|
commands=commands,
|
|
123
131
|
)
|
|
124
132
|
raise ValueError(
|
|
@@ -341,7 +349,6 @@ def clean_up_commands(
|
|
|
341
349
|
clean_commands: List[Command] = []
|
|
342
350
|
|
|
343
351
|
for command in commands:
|
|
344
|
-
|
|
345
352
|
if isinstance(command, SetSlotCommand):
|
|
346
353
|
clean_commands = clean_up_slot_command(
|
|
347
354
|
clean_commands, command, tracker, all_flows, slots_so_far
|
|
@@ -355,6 +362,19 @@ def clean_up_commands(
|
|
|
355
362
|
".skip_command_flow_already_cancelled",
|
|
356
363
|
command=command,
|
|
357
364
|
)
|
|
365
|
+
|
|
366
|
+
# if there is a cannot handle command after the previous step,
|
|
367
|
+
# we don't want to add another one
|
|
368
|
+
elif isinstance(command, CannotHandleCommand) and contains_command(
|
|
369
|
+
clean_commands, CannotHandleCommand
|
|
370
|
+
):
|
|
371
|
+
structlogger.debug(
|
|
372
|
+
"command_processor"
|
|
373
|
+
".clean_up_commands"
|
|
374
|
+
".skip_command_already_has_cannot_handle",
|
|
375
|
+
command=command,
|
|
376
|
+
)
|
|
377
|
+
|
|
358
378
|
elif isinstance(command, StartFlowCommand) and command.flow == active_flow:
|
|
359
379
|
# drop a start flow command if the starting flow is equal to the currently
|
|
360
380
|
# active flow
|
|
@@ -388,6 +408,13 @@ def clean_up_commands(
|
|
|
388
408
|
else:
|
|
389
409
|
clean_commands.append(command)
|
|
390
410
|
|
|
411
|
+
# when coexistence is enabled, by default there will be a SetSlotCommand
|
|
412
|
+
# for the ROUTE_TO_CALM_SLOT slot.
|
|
413
|
+
if tracker.has_coexistence_routing_slot and len(clean_commands) > 2:
|
|
414
|
+
clean_commands = filter_cannot_handle_command_for_skipped_slots(clean_commands)
|
|
415
|
+
elif not tracker.has_coexistence_routing_slot and len(clean_commands) > 1:
|
|
416
|
+
clean_commands = filter_cannot_handle_command_for_skipped_slots(clean_commands)
|
|
417
|
+
|
|
391
418
|
structlogger.debug(
|
|
392
419
|
"command_processor.clean_up_commands.final_commands",
|
|
393
420
|
command=clean_commands,
|
|
@@ -460,6 +487,22 @@ def clean_up_slot_command(
|
|
|
460
487
|
stack = tracker.stack
|
|
461
488
|
|
|
462
489
|
resulting_commands = commands_so_far[:]
|
|
490
|
+
|
|
491
|
+
slot = tracker.slots.get(command.name)
|
|
492
|
+
if slot is None:
|
|
493
|
+
structlogger.debug(
|
|
494
|
+
"command_processor.clean_up_slot_command.skip_command_slot_not_in_domain",
|
|
495
|
+
command=command,
|
|
496
|
+
)
|
|
497
|
+
return resulting_commands
|
|
498
|
+
|
|
499
|
+
if not should_slot_be_set(slot, command):
|
|
500
|
+
cannot_handle = CannotHandleCommand(reason=CANNOT_HANDLE_REASON)
|
|
501
|
+
if cannot_handle not in resulting_commands:
|
|
502
|
+
resulting_commands.append(cannot_handle)
|
|
503
|
+
|
|
504
|
+
return resulting_commands
|
|
505
|
+
|
|
463
506
|
if command.name in slots_so_far and command.name != ROUTE_TO_CALM_SLOT:
|
|
464
507
|
current_collect_info = get_current_collect_step(stack, all_flows)
|
|
465
508
|
|
|
@@ -576,3 +619,69 @@ def clean_up_chitchat_command(
|
|
|
576
619
|
)
|
|
577
620
|
|
|
578
621
|
return resulting_commands
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def should_slot_be_set(slot: Slot, command: SetSlotCommand) -> bool:
|
|
625
|
+
"""Check if a slot should be set by a command."""
|
|
626
|
+
if command.extractor == SetSlotExtractor.COMMAND_PAYLOAD_READER.value:
|
|
627
|
+
# if the command is issued by the command payload reader, it means the slot
|
|
628
|
+
# was set deterministically via a response button. In this case,
|
|
629
|
+
# we can always set it
|
|
630
|
+
return True
|
|
631
|
+
|
|
632
|
+
slot_mappings = slot.mappings
|
|
633
|
+
|
|
634
|
+
if not slot_mappings:
|
|
635
|
+
slot_mappings = [{"type": SlotMappingType.FROM_LLM.value}]
|
|
636
|
+
|
|
637
|
+
for mapping in slot_mappings:
|
|
638
|
+
mapping_type = SlotMappingType(
|
|
639
|
+
mapping.get("type", SlotMappingType.FROM_LLM.value)
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
should_be_set_by_llm = (
|
|
643
|
+
command.extractor == SetSlotExtractor.LLM.value
|
|
644
|
+
and mapping_type == SlotMappingType.FROM_LLM
|
|
645
|
+
)
|
|
646
|
+
should_be_set_by_nlu = (
|
|
647
|
+
command.extractor == SetSlotExtractor.NLU.value
|
|
648
|
+
and mapping_type.is_predefined_type()
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
if should_be_set_by_llm or should_be_set_by_nlu:
|
|
652
|
+
# if the extractor matches the mapping type, we can continue
|
|
653
|
+
# setting the slot
|
|
654
|
+
break
|
|
655
|
+
|
|
656
|
+
structlogger.debug(
|
|
657
|
+
"command_processor.clean_up_slot_command.skip_command.extractor_"
|
|
658
|
+
"does_not_match_slot_mapping",
|
|
659
|
+
extractor=command.extractor,
|
|
660
|
+
slot_name=slot.name,
|
|
661
|
+
mapping_type=mapping_type.value,
|
|
662
|
+
)
|
|
663
|
+
return False
|
|
664
|
+
|
|
665
|
+
return True
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def filter_cannot_handle_command_for_skipped_slots(
|
|
669
|
+
clean_commands: List[Command],
|
|
670
|
+
) -> List[Command]:
|
|
671
|
+
"""Filter out a 'cannot handle' command for skipped slots.
|
|
672
|
+
|
|
673
|
+
This is used to filter out a 'cannot handle' command for skipped slots
|
|
674
|
+
in case other commands are present.
|
|
675
|
+
|
|
676
|
+
Returns:
|
|
677
|
+
The filtered commands.
|
|
678
|
+
"""
|
|
679
|
+
return [
|
|
680
|
+
command
|
|
681
|
+
for command in clean_commands
|
|
682
|
+
if not (
|
|
683
|
+
isinstance(command, CannotHandleCommand)
|
|
684
|
+
and command.reason
|
|
685
|
+
and CANNOT_HANDLE_REASON == command.reason
|
|
686
|
+
)
|
|
687
|
+
]
|
rasa/e2e_test/constants.py
CHANGED
rasa/e2e_test/e2e_test_case.py
CHANGED
|
@@ -8,6 +8,7 @@ from rasa.e2e_test.constants import (
|
|
|
8
8
|
KEY_BOT_INPUT,
|
|
9
9
|
KEY_BOT_UTTERED,
|
|
10
10
|
KEY_FIXTURES,
|
|
11
|
+
KEY_METADATA,
|
|
11
12
|
KEY_SLOT_NOT_SET,
|
|
12
13
|
KEY_SLOT_SET,
|
|
13
14
|
KEY_STEPS,
|
|
@@ -63,6 +64,7 @@ class TestStep:
|
|
|
63
64
|
slot_was_not_set: bool = False
|
|
64
65
|
_slot_instance: Optional[Union[Text, Dict[Text, Any]]] = None
|
|
65
66
|
_underlying: Optional[Dict[Text, Any]] = None
|
|
67
|
+
metadata_name: Optional[Text] = None
|
|
66
68
|
|
|
67
69
|
@staticmethod
|
|
68
70
|
def from_dict(test_step_dict: Dict[Text, Any]) -> "TestStep":
|
|
@@ -71,6 +73,8 @@ class TestStep:
|
|
|
71
73
|
Example:
|
|
72
74
|
>>> TestStep.from_dict({"user": "hello"})
|
|
73
75
|
TestStep(text="hello", actor="user")
|
|
76
|
+
>>> TestStep.from_dict({"user": "hello", metadata: "some_metadata"})
|
|
77
|
+
TestStep(text="hello", actor="user", metadata_name="some_metadata")
|
|
74
78
|
>>> TestStep.from_dict({"bot": "hello world"})
|
|
75
79
|
TestStep(text="hello world", actor="bot")
|
|
76
80
|
|
|
@@ -94,6 +98,7 @@ class TestStep:
|
|
|
94
98
|
slot_was_not_set=bool(test_step_dict.get(KEY_SLOT_NOT_SET)),
|
|
95
99
|
_slot_instance=slot_instance,
|
|
96
100
|
_underlying=test_step_dict,
|
|
101
|
+
metadata_name=test_step_dict.get(KEY_METADATA, ""),
|
|
97
102
|
)
|
|
98
103
|
|
|
99
104
|
@staticmethod
|
|
@@ -269,6 +274,7 @@ class TestCase:
|
|
|
269
274
|
file: Optional[Text] = None
|
|
270
275
|
line: Optional[int] = None
|
|
271
276
|
fixture_names: Optional[List[Text]] = None
|
|
277
|
+
metadata_name: Optional[Text] = None
|
|
272
278
|
|
|
273
279
|
@staticmethod
|
|
274
280
|
def from_dict(
|
|
@@ -311,6 +317,7 @@ class TestCase:
|
|
|
311
317
|
if hasattr(input_test_case, "lc")
|
|
312
318
|
else None,
|
|
313
319
|
fixture_names=input_test_case.get(KEY_FIXTURES),
|
|
320
|
+
metadata_name=input_test_case.get(KEY_METADATA),
|
|
314
321
|
)
|
|
315
322
|
|
|
316
323
|
def file_with_line(self) -> Text:
|
|
@@ -320,3 +327,40 @@ class TestCase:
|
|
|
320
327
|
|
|
321
328
|
line = str(self.line) if self.line is not None else ""
|
|
322
329
|
return f"{self.file}:{line}"
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
@dataclass(frozen=True)
|
|
333
|
+
class Metadata:
|
|
334
|
+
"""Class for storing an input metadata."""
|
|
335
|
+
|
|
336
|
+
name: Text
|
|
337
|
+
metadata: Dict[Text, Any]
|
|
338
|
+
|
|
339
|
+
@staticmethod
|
|
340
|
+
def from_dict(metadata_dict: Dict[Text, Any]) -> "Metadata":
|
|
341
|
+
"""Creates a metadata from a dictionary.
|
|
342
|
+
|
|
343
|
+
Example:
|
|
344
|
+
>>> Metadata.from_dict({"some_metadata": {"room": "test_room"}})
|
|
345
|
+
Metadata(name="some_metadata", metadata={"room": "test_room"})
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
metadata_dict: Dictionary containing the metadata.
|
|
349
|
+
"""
|
|
350
|
+
return Metadata(
|
|
351
|
+
name=next(iter(metadata_dict.keys())),
|
|
352
|
+
metadata={
|
|
353
|
+
metadata_name: metadata_value
|
|
354
|
+
for metadata in metadata_dict.values()
|
|
355
|
+
for metadata_name, metadata_value in metadata.items()
|
|
356
|
+
},
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
@dataclass(frozen=True)
|
|
361
|
+
class TestSuite:
|
|
362
|
+
"""Class for representing all top level test suite keys."""
|
|
363
|
+
|
|
364
|
+
test_cases: List[TestCase]
|
|
365
|
+
fixtures: List[Fixture]
|
|
366
|
+
metadata: List[Metadata]
|
rasa/e2e_test/e2e_test_runner.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import copy
|
|
2
3
|
import datetime
|
|
3
4
|
import difflib
|
|
4
5
|
import logging
|
|
5
6
|
from asyncio import CancelledError
|
|
6
|
-
from typing import Dict, List, Optional, Text, Tuple, Union
|
|
7
|
+
from typing import Any, Dict, List, Optional, Text, Tuple, Union
|
|
7
8
|
from urllib.parse import urlparse
|
|
8
9
|
|
|
9
10
|
import rasa.shared.utils.io
|
|
@@ -19,6 +20,7 @@ from rasa.utils.endpoints import EndpointConfig
|
|
|
19
20
|
from rasa.e2e_test.e2e_test_case import (
|
|
20
21
|
ActualStepOutput,
|
|
21
22
|
Fixture,
|
|
23
|
+
Metadata,
|
|
22
24
|
TestCase,
|
|
23
25
|
TestStep,
|
|
24
26
|
)
|
|
@@ -85,6 +87,8 @@ class E2ETestRunner:
|
|
|
85
87
|
collector: CollectingOutputChannel,
|
|
86
88
|
steps: List[TestStep],
|
|
87
89
|
sender_id: Text,
|
|
90
|
+
test_case_metadata: Optional[Metadata] = None,
|
|
91
|
+
input_metadata: Optional[List[Metadata]] = None,
|
|
88
92
|
) -> TEST_TURNS_TYPE:
|
|
89
93
|
"""Runs dialogue prediction.
|
|
90
94
|
|
|
@@ -94,12 +98,12 @@ class E2ETestRunner:
|
|
|
94
98
|
sender_id: The test case name with added timestamp suffix.
|
|
95
99
|
|
|
96
100
|
Returns:
|
|
97
|
-
|
|
101
|
+
Test turns: {turn_sequence (int) : TestStep or ActualStepOutput}.
|
|
98
102
|
"""
|
|
99
103
|
turns: TEST_TURNS_TYPE = {}
|
|
100
104
|
event_cursor = 0
|
|
101
105
|
|
|
102
|
-
tracker = await self.agent.processor.fetch_tracker_with_initial_session( # type: ignore[union-attr]
|
|
106
|
+
tracker = await self.agent.processor.fetch_tracker_with_initial_session( # type: ignore[union-attr]
|
|
103
107
|
sender_id
|
|
104
108
|
)
|
|
105
109
|
# turn -1 i used to contain events that happen during
|
|
@@ -123,12 +127,24 @@ class E2ETestRunner:
|
|
|
123
127
|
)
|
|
124
128
|
continue
|
|
125
129
|
|
|
130
|
+
metadata = test_case_metadata.metadata if test_case_metadata else {}
|
|
131
|
+
|
|
132
|
+
if input_metadata:
|
|
133
|
+
step_metadata = self.filter_metadata_for_input(
|
|
134
|
+
step.metadata_name, input_metadata
|
|
135
|
+
)
|
|
136
|
+
step_metadata_dict = step_metadata.metadata if step_metadata else {}
|
|
137
|
+
metadata = self.merge_metadata(
|
|
138
|
+
sender_id, step.text, metadata, step_metadata_dict
|
|
139
|
+
)
|
|
140
|
+
|
|
126
141
|
try:
|
|
127
142
|
await self.agent.handle_message(
|
|
128
143
|
UserMessage(
|
|
129
144
|
step.text,
|
|
130
145
|
collector,
|
|
131
146
|
sender_id,
|
|
147
|
+
metadata=metadata,
|
|
132
148
|
)
|
|
133
149
|
)
|
|
134
150
|
except CancelledError:
|
|
@@ -147,6 +163,49 @@ class E2ETestRunner:
|
|
|
147
163
|
)
|
|
148
164
|
return turns
|
|
149
165
|
|
|
166
|
+
@staticmethod
|
|
167
|
+
def merge_metadata(
|
|
168
|
+
sender_id: Text,
|
|
169
|
+
step_text: Text,
|
|
170
|
+
test_case_metadata: Dict[Text, Text],
|
|
171
|
+
step_metadata: Dict[Text, Text],
|
|
172
|
+
) -> Dict[Text, Text]:
|
|
173
|
+
"""Merges the test case and user step metadata.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
sender_id: The test case name with added timestamp suffix.
|
|
177
|
+
step_text: The user step text.
|
|
178
|
+
test_case_metadata: The test case metadata dict.
|
|
179
|
+
step_metadata: The user step metadata dict.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
A dictionary with the merged metadata.
|
|
183
|
+
"""
|
|
184
|
+
if not test_case_metadata:
|
|
185
|
+
return step_metadata
|
|
186
|
+
if not step_metadata:
|
|
187
|
+
return test_case_metadata
|
|
188
|
+
|
|
189
|
+
keys_to_overwrite = []
|
|
190
|
+
|
|
191
|
+
for key in step_metadata.keys():
|
|
192
|
+
if key in test_case_metadata.keys():
|
|
193
|
+
keys_to_overwrite.append(key)
|
|
194
|
+
|
|
195
|
+
if keys_to_overwrite:
|
|
196
|
+
test_case_name = sender_id.rsplit("_", 1)[0]
|
|
197
|
+
logger.warning(
|
|
198
|
+
f"Metadata {keys_to_overwrite} exist in both the test case "
|
|
199
|
+
f"'{test_case_name}' and the user step '{step_text}'. "
|
|
200
|
+
"The user step metadata takes precedence and will "
|
|
201
|
+
"override the test case metadata."
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
merged_metadata = copy.deepcopy(test_case_metadata)
|
|
205
|
+
merged_metadata.update(step_metadata)
|
|
206
|
+
|
|
207
|
+
return merged_metadata
|
|
208
|
+
|
|
150
209
|
@staticmethod
|
|
151
210
|
def get_actual_step_output(
|
|
152
211
|
tracker: DialogueStateTracker,
|
|
@@ -310,10 +369,10 @@ class E2ETestRunner:
|
|
|
310
369
|
if failed_step.text is not None:
|
|
311
370
|
diff_test_text = f"{failed_step.actor}: {failed_step.text}"
|
|
312
371
|
diff_actual_text = NO_RESPONSE
|
|
313
|
-
event: Optional[
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
372
|
+
event: Optional[Union[BotUttered, SlotSet]] = (
|
|
373
|
+
cls._find_first_non_matched_utterance(
|
|
374
|
+
test_response, bot_utter_test_steps
|
|
375
|
+
)
|
|
317
376
|
)
|
|
318
377
|
if event and isinstance(event, BotUttered):
|
|
319
378
|
test_response.remove_bot_uttered_event(event)
|
|
@@ -533,7 +592,7 @@ class E2ETestRunner:
|
|
|
533
592
|
"""
|
|
534
593
|
if not fixtures:
|
|
535
594
|
return
|
|
536
|
-
tracker = await self.agent.processor.fetch_tracker_with_initial_session( # type: ignore[union-attr]
|
|
595
|
+
tracker = await self.agent.processor.fetch_tracker_with_initial_session( # type: ignore[union-attr]
|
|
537
596
|
sender_id
|
|
538
597
|
)
|
|
539
598
|
|
|
@@ -564,11 +623,43 @@ class E2ETestRunner:
|
|
|
564
623
|
)
|
|
565
624
|
)
|
|
566
625
|
|
|
626
|
+
@staticmethod
|
|
627
|
+
def filter_metadata_for_input(
|
|
628
|
+
metadata_name: Optional[Text], test_suite_metadata: List[Metadata]
|
|
629
|
+
) -> Optional[Metadata]:
|
|
630
|
+
"""Filters the test suite metadata for a metadata name.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
metadata_name: The test case or user step metadata name.
|
|
634
|
+
test_suite_metadata: The top level list of all metadata definitions.
|
|
635
|
+
|
|
636
|
+
Returns:
|
|
637
|
+
The filtered metadata.
|
|
638
|
+
"""
|
|
639
|
+
if not metadata_name:
|
|
640
|
+
return None
|
|
641
|
+
|
|
642
|
+
filtered_metadata = list(
|
|
643
|
+
filter(
|
|
644
|
+
lambda metadata: metadata_name and metadata.name == metadata_name,
|
|
645
|
+
test_suite_metadata,
|
|
646
|
+
)
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
if not filtered_metadata:
|
|
650
|
+
logger.warning(
|
|
651
|
+
f"Metadata '{metadata_name}' is not defined in the input metadata."
|
|
652
|
+
)
|
|
653
|
+
return None
|
|
654
|
+
|
|
655
|
+
return filtered_metadata[0]
|
|
656
|
+
|
|
567
657
|
async def run_tests(
|
|
568
658
|
self,
|
|
569
659
|
input_test_cases: List[TestCase],
|
|
570
660
|
input_fixtures: List[Fixture],
|
|
571
661
|
fail_fast: bool = False,
|
|
662
|
+
**kwargs: Any,
|
|
572
663
|
) -> List["TestResult"]:
|
|
573
664
|
"""Runs the test cases.
|
|
574
665
|
|
|
@@ -576,14 +667,16 @@ class E2ETestRunner:
|
|
|
576
667
|
input_test_cases: Input test cases.
|
|
577
668
|
input_fixtures: Input fixtures.
|
|
578
669
|
fail_fast: Whether to fail fast.
|
|
670
|
+
**kwargs: Additional arguments which are passed here.
|
|
579
671
|
|
|
580
672
|
Returns:
|
|
581
|
-
|
|
673
|
+
List of test results.
|
|
582
674
|
"""
|
|
583
675
|
results = []
|
|
676
|
+
input_metadata = kwargs.get("input_metadata", None)
|
|
584
677
|
|
|
585
678
|
# telemetry call for tracking test runs
|
|
586
|
-
track_e2e_test_run(input_test_cases, input_fixtures)
|
|
679
|
+
track_e2e_test_run(input_test_cases, input_fixtures, input_metadata)
|
|
587
680
|
|
|
588
681
|
for test_case in input_test_cases:
|
|
589
682
|
collector = CollectingOutputChannel()
|
|
@@ -597,8 +690,18 @@ class E2ETestRunner:
|
|
|
597
690
|
)
|
|
598
691
|
await self.set_up_fixtures(test_fixtures, sender_id)
|
|
599
692
|
|
|
693
|
+
test_case_metadata = None
|
|
694
|
+
if input_metadata:
|
|
695
|
+
test_case_metadata = self.filter_metadata_for_input(
|
|
696
|
+
test_case.metadata_name, input_metadata
|
|
697
|
+
)
|
|
698
|
+
|
|
600
699
|
tracker = await self.run_prediction_loop(
|
|
601
|
-
collector,
|
|
700
|
+
collector,
|
|
701
|
+
test_case.steps,
|
|
702
|
+
sender_id,
|
|
703
|
+
test_case_metadata,
|
|
704
|
+
input_metadata,
|
|
602
705
|
)
|
|
603
706
|
|
|
604
707
|
test_result = self.generate_test_result(tracker, test_case)
|
|
@@ -13,6 +13,18 @@ mapping:
|
|
|
13
13
|
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
14
14
|
type: any
|
|
15
15
|
|
|
16
|
+
metadata:
|
|
17
|
+
allowempty: True
|
|
18
|
+
type: "seq"
|
|
19
|
+
sequence:
|
|
20
|
+
- type: map
|
|
21
|
+
mapping:
|
|
22
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
23
|
+
type: map
|
|
24
|
+
mapping:
|
|
25
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
26
|
+
type: any
|
|
27
|
+
|
|
16
28
|
test_cases:
|
|
17
29
|
type: "seq"
|
|
18
30
|
sequence:
|
|
@@ -27,6 +39,9 @@ mapping:
|
|
|
27
39
|
sequence:
|
|
28
40
|
- type: "str"
|
|
29
41
|
pattern: ^[a-zA-Z_]+[a-zA-Z0-9_]*$
|
|
42
|
+
metadata:
|
|
43
|
+
type: "str"
|
|
44
|
+
pattern: ^[a-zA-Z_]+[a-zA-Z0-9_]*$
|
|
30
45
|
steps:
|
|
31
46
|
type: "seq"
|
|
32
47
|
matching: "any"
|
|
@@ -34,7 +49,10 @@ mapping:
|
|
|
34
49
|
- type: map
|
|
35
50
|
mapping:
|
|
36
51
|
user:
|
|
52
|
+
type: str
|
|
53
|
+
metadata:
|
|
37
54
|
type: "str"
|
|
55
|
+
pattern: ^[a-zA-Z_]+[a-zA-Z0-9_]*$
|
|
38
56
|
- type: map
|
|
39
57
|
mapping:
|
|
40
58
|
utter:
|
rasa/engine/caching.py
CHANGED
rasa/engine/graph.py
CHANGED
|
@@ -108,10 +108,10 @@ class GraphSchema:
|
|
|
108
108
|
nodes = {}
|
|
109
109
|
for node_name, serialized_node in serialized_graph_schema["nodes"].items():
|
|
110
110
|
try:
|
|
111
|
-
serialized_node[
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
serialized_node["uses"] = (
|
|
112
|
+
rasa.shared.utils.common.class_from_module_path(
|
|
113
|
+
serialized_node["uses"]
|
|
114
|
+
)
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
resource = serialized_node["resource"]
|
|
@@ -172,6 +172,18 @@ class GraphSchema:
|
|
|
172
172
|
return True
|
|
173
173
|
return False
|
|
174
174
|
|
|
175
|
+
def count_nodes_of_a_given_type(
|
|
176
|
+
self, node_type: Type, include_subtypes: bool = True
|
|
177
|
+
) -> int:
|
|
178
|
+
"""Counts the number of the nodes of specified class"""
|
|
179
|
+
counter = 0
|
|
180
|
+
for node in self.nodes.values():
|
|
181
|
+
if (node.uses is node_type) or (
|
|
182
|
+
include_subtypes and issubclass(node.uses, node_type)
|
|
183
|
+
):
|
|
184
|
+
counter += 1
|
|
185
|
+
return counter
|
|
186
|
+
|
|
175
187
|
|
|
176
188
|
class GraphComponent(ABC):
|
|
177
189
|
"""Interface for any component which will run in a graph."""
|
|
@@ -206,7 +218,7 @@ class GraphComponent(ABC):
|
|
|
206
218
|
|
|
207
219
|
@classmethod
|
|
208
220
|
def load(
|
|
209
|
-
cls,
|
|
221
|
+
cls: Any,
|
|
210
222
|
config: Dict[Text, Any],
|
|
211
223
|
model_storage: ModelStorage,
|
|
212
224
|
resource: Resource,
|
|
@@ -267,7 +279,7 @@ class GraphComponent(ABC):
|
|
|
267
279
|
return []
|
|
268
280
|
|
|
269
281
|
@classmethod
|
|
270
|
-
def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
|
|
282
|
+
def fingerprint_addon(cls: Any, config: Dict[str, Any]) -> Optional[str]:
|
|
271
283
|
"""Adds additional data to the fingerprint calculation.
|
|
272
284
|
|
|
273
285
|
This is useful if a component uses external data that is not provided
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# The config recipe.
|
|
2
|
-
# https://rasa.com/docs/rasa/model-configuration/
|
|
2
|
+
# https://rasa.com/docs/rasa-pro/nlu-based-assistants/model-configuration/
|
|
3
3
|
recipe: default.v1
|
|
4
4
|
|
|
5
5
|
# The assistant project unique identifier
|
|
@@ -7,7 +7,7 @@ recipe: default.v1
|
|
|
7
7
|
assistant_id: placeholder_default
|
|
8
8
|
|
|
9
9
|
# Configuration for the Rasa NLU components.
|
|
10
|
-
# https://rasa.com/docs/rasa/components
|
|
10
|
+
# https://rasa.com/docs/rasa-pro/nlu-based-assistants/components
|
|
11
11
|
language: en
|
|
12
12
|
|
|
13
13
|
pipeline:
|
|
@@ -31,7 +31,7 @@ pipeline:
|
|
|
31
31
|
ambiguity_threshold: 0.1
|
|
32
32
|
|
|
33
33
|
# Configuration for the Rasa Core policies.
|
|
34
|
-
# https://rasa.com/docs/rasa/policies
|
|
34
|
+
# https://rasa.com/docs/rasa-pro/concepts/policies/policy-overview/
|
|
35
35
|
policies:
|
|
36
36
|
- name: MemoizationPolicy
|
|
37
37
|
- name: RulePolicy
|
|
@@ -9,7 +9,7 @@ from rasa.dialogue_understanding.generator.nlu_command_adapter import NLUCommand
|
|
|
9
9
|
from rasa.nlu.classifiers.diet_classifier import DIETClassifier
|
|
10
10
|
from rasa.nlu.classifiers.fallback_classifier import FallbackClassifier
|
|
11
11
|
from rasa.nlu.classifiers.keyword_intent_classifier import KeywordIntentClassifier
|
|
12
|
-
from rasa.dialogue_understanding.generator
|
|
12
|
+
from rasa.dialogue_understanding.generator import (
|
|
13
13
|
LLMCommandGenerator,
|
|
14
14
|
)
|
|
15
15
|
from rasa.nlu.classifiers.llm_intent_classifier import LLMIntentClassifier
|
|
@@ -157,10 +157,10 @@ class DefaultV1Recipe(Recipe):
|
|
|
157
157
|
else:
|
|
158
158
|
unique_types = set(component_types)
|
|
159
159
|
|
|
160
|
-
cls._registered_components[
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
cls._registered_components[registered_class.__name__] = (
|
|
161
|
+
cls.RegisteredComponent(
|
|
162
|
+
registered_class, unique_types, is_trainable, model_from
|
|
163
|
+
)
|
|
164
164
|
)
|
|
165
165
|
return registered_class
|
|
166
166
|
|
|
@@ -699,7 +699,6 @@ class DefaultV1Recipe(Recipe):
|
|
|
699
699
|
preprocessors: List[Text],
|
|
700
700
|
train_nodes: Dict[Text, SchemaNode],
|
|
701
701
|
) -> Dict[Text, SchemaNode]:
|
|
702
|
-
|
|
703
702
|
predict_config = copy.deepcopy(config)
|
|
704
703
|
predict_nodes = {}
|
|
705
704
|
|
rasa/engine/recipes/recipe.py
CHANGED
|
@@ -33,7 +33,7 @@ class Recipe(abc.ABC):
|
|
|
33
33
|
|
|
34
34
|
if name is None:
|
|
35
35
|
rasa.shared.utils.io.raise_deprecation_warning(
|
|
36
|
-
"From Rasa
|
|
36
|
+
"From Rasa Pro 4.0.0 onwards it will be required to specify "
|
|
37
37
|
"a recipe in your model configuration. Defaulting to recipe "
|
|
38
38
|
f"'{DefaultV1Recipe.name}'."
|
|
39
39
|
)
|
rasa/engine/runner/dask.py
CHANGED
|
@@ -222,9 +222,7 @@ async def execute_dask_graph(dsk: Dict[str, Any], result: List[str]) -> Any:
|
|
|
222
222
|
state = {}
|
|
223
223
|
keyorder = dask.local.order(dsk) # type:ignore[no-untyped-call]
|
|
224
224
|
|
|
225
|
-
state = dask.local.start_state_from_dask(
|
|
226
|
-
dsk, cache=cache, sortkey=keyorder.get
|
|
227
|
-
) # type:ignore[no-untyped-call]
|
|
225
|
+
state = dask.local.start_state_from_dask(dsk, cache=cache, sortkey=keyorder.get) # type:ignore[no-untyped-call]
|
|
228
226
|
|
|
229
227
|
if state["waiting"] and not state["ready"]:
|
|
230
228
|
raise ValueError("Found no accessible jobs in dask")
|
|
@@ -237,17 +235,13 @@ async def execute_dask_graph(dsk: Dict[str, Any], result: List[str]) -> Any:
|
|
|
237
235
|
# Notify task is running
|
|
238
236
|
state["running"].add(key)
|
|
239
237
|
|
|
240
|
-
dependencies = dask.local.get_dependencies(
|
|
241
|
-
dsk, key
|
|
242
|
-
) # type:ignore[no-untyped-call]
|
|
238
|
+
dependencies = dask.local.get_dependencies(dsk, key) # type:ignore[no-untyped-call]
|
|
243
239
|
# Prep args to send
|
|
244
240
|
data = {dep: state["cache"][dep] for dep in dependencies}
|
|
245
241
|
|
|
246
242
|
task_result = await _execute_task(dsk[key], data)
|
|
247
243
|
state["cache"][key] = task_result
|
|
248
|
-
dask.local.finish_task(
|
|
249
|
-
dsk, key, state, results, keyorder.get
|
|
250
|
-
) # type:ignore[no-untyped-call]
|
|
244
|
+
dask.local.finish_task(dsk, key, state, results, keyorder.get) # type:ignore[no-untyped-call]
|
|
251
245
|
|
|
252
246
|
# Main loop, wait on tasks to finish, insert new ones
|
|
253
247
|
while state["ready"]:
|