rasa-pro 3.8.17__py3-none-any.whl → 3.9.14__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 +5 -5
- 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/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 +2 -4
- rasa/core/featurizers/tracker_featurizers.py +0 -7
- 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 +28 -30
- rasa/core/policies/unexpected_intent_policy.py +1 -2
- 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 +34 -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 +44 -39
- rasa/dialogue_understanding/processor/command_processor.py +111 -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 +8 -14
- rasa/nlu/extractors/crf_entity_extractor.py +4 -4
- 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 +2 -4
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +9 -12
- 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/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 -0
- 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 +6 -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 +9 -11
- 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.17.dist-info → rasa_pro-3.9.14.dist-info}/METADATA +22 -22
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/RECORD +271 -253
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
- /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/NOTICE +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/WHEEL +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/entry_points.txt +0 -0
|
@@ -99,7 +99,6 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
99
99
|
return ["sklearn"]
|
|
100
100
|
|
|
101
101
|
def _load_count_vect_params(self) -> None:
|
|
102
|
-
|
|
103
102
|
# Use shared vocabulary between text and all other attributes of Message
|
|
104
103
|
self.use_shared_vocab = self._config["use_shared_vocab"]
|
|
105
104
|
|
|
@@ -340,7 +339,7 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
340
339
|
|
|
341
340
|
@staticmethod
|
|
342
341
|
def _convert_attribute_tokens_to_texts(
|
|
343
|
-
attribute_tokens: Dict[Text, List[List[Text]]]
|
|
342
|
+
attribute_tokens: Dict[Text, List[List[Text]]],
|
|
344
343
|
) -> Dict[Text, List[Text]]:
|
|
345
344
|
attribute_texts = {}
|
|
346
345
|
|
|
@@ -659,7 +658,6 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
659
658
|
|
|
660
659
|
for message in messages:
|
|
661
660
|
for attribute in self._attributes:
|
|
662
|
-
|
|
663
661
|
message_tokens = self._get_processed_message_tokens_by_attribute(
|
|
664
662
|
message, attribute
|
|
665
663
|
)
|
|
@@ -685,7 +683,7 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
685
683
|
|
|
686
684
|
@staticmethod
|
|
687
685
|
def _is_any_model_trained(
|
|
688
|
-
attribute_vocabularies: Dict[Text, Optional[Dict[Text, int]]]
|
|
686
|
+
attribute_vocabularies: Dict[Text, Optional[Dict[Text, int]]],
|
|
689
687
|
) -> bool:
|
|
690
688
|
"""Check if any model got trained."""
|
|
691
689
|
return any(value is not None for value in attribute_vocabularies.values())
|
|
@@ -76,9 +76,7 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
76
76
|
|
|
77
77
|
# NOTE: "suffix5" of the token "is" will be "is". Hence, when combining multiple
|
|
78
78
|
# prefixes, short words will be represented/encoded repeatedly.
|
|
79
|
-
_FUNCTION_DICT: Dict[
|
|
80
|
-
Text, Callable[[Token], Union[Text, bool, None]]
|
|
81
|
-
] = { # noqa: RUF012
|
|
79
|
+
_FUNCTION_DICT: Dict[Text, Callable[[Token], Union[Text, bool, None]]] = { # noqa: RUF012
|
|
82
80
|
"low": lambda token: token.text.islower(),
|
|
83
81
|
"title": lambda token: token.text.istitle(),
|
|
84
82
|
"prefix5": lambda token: token.text[:5],
|
|
@@ -329,7 +327,6 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
329
327
|
assert len(window_range) == window_size
|
|
330
328
|
|
|
331
329
|
for anchor in range(len(tokens)):
|
|
332
|
-
|
|
333
330
|
token_features: Dict[Tuple[int, Text], Text] = {}
|
|
334
331
|
|
|
335
332
|
for window_position, relative_position in enumerate(window_range):
|
|
@@ -341,13 +338,13 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
341
338
|
|
|
342
339
|
token = tokens[absolute_position]
|
|
343
340
|
for feature_name in self._feature_config[window_position]:
|
|
344
|
-
token_features[
|
|
345
|
-
(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
341
|
+
token_features[(window_position, feature_name)] = (
|
|
342
|
+
self._extract_raw_features_from_token(
|
|
343
|
+
token=token,
|
|
344
|
+
feature_name=feature_name,
|
|
345
|
+
token_position=absolute_position,
|
|
346
|
+
num_tokens=len(tokens),
|
|
347
|
+
)
|
|
351
348
|
)
|
|
352
349
|
|
|
353
350
|
sentence_features.append(token_features)
|
|
@@ -356,7 +353,7 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
|
|
|
356
353
|
|
|
357
354
|
@staticmethod
|
|
358
355
|
def _build_feature_to_index_map(
|
|
359
|
-
feature_vocabulary: Dict[Tuple[int, Text], Set[Text]]
|
|
356
|
+
feature_vocabulary: Dict[Tuple[int, Text], Set[Text]],
|
|
360
357
|
) -> Dict[Tuple[int, Text], Dict[Text, int]]:
|
|
361
358
|
"""Creates a nested dictionary for mapping raw features to indices.
|
|
362
359
|
|
rasa/nlu/persistor.py
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
import
|
|
2
|
+
import structlog
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
5
|
from typing import Optional, Text, Tuple, TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from rasa.shared.exceptions import RasaException
|
|
8
|
+
|
|
7
9
|
import rasa.shared.utils.common
|
|
8
10
|
import rasa.utils.common
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
13
|
from azure.storage.blob import ContainerClient
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
structlogger = structlog.get_logger()
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
def get_persistor(name: Text) -> Optional["Persistor"]:
|
|
@@ -95,7 +97,6 @@ class Persistor(abc.ABC):
|
|
|
95
97
|
|
|
96
98
|
@staticmethod
|
|
97
99
|
def _tar_name(model_name: Text, include_extension: bool = True) -> Text:
|
|
98
|
-
|
|
99
100
|
ext = ".tar.gz" if include_extension else ""
|
|
100
101
|
return f"{model_name}{ext}"
|
|
101
102
|
|
|
@@ -129,20 +130,36 @@ class AWSPersistor(Persistor):
|
|
|
129
130
|
def _ensure_bucket_exists(
|
|
130
131
|
self, bucket_name: Text, region_name: Optional[Text] = None
|
|
131
132
|
) -> None:
|
|
132
|
-
import boto3
|
|
133
133
|
import botocore
|
|
134
134
|
|
|
135
|
-
if not region_name:
|
|
136
|
-
region_name = boto3.DEFAULT_SESSION.region_name
|
|
137
|
-
|
|
138
|
-
bucket_config = {"LocationConstraint": region_name}
|
|
139
135
|
# noinspection PyUnresolvedReferences
|
|
140
136
|
try:
|
|
141
|
-
self.s3.
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
self.s3.meta.client.head_bucket(Bucket=bucket_name)
|
|
138
|
+
except botocore.exceptions.ClientError as e:
|
|
139
|
+
error_code = int(e.response["Error"]["Code"])
|
|
140
|
+
if error_code == 403:
|
|
141
|
+
log = (
|
|
142
|
+
f"Access to the specified bucket '{bucket_name}' is forbidden. "
|
|
143
|
+
"Please make sure you have the necessary "
|
|
144
|
+
"permission to access the bucket."
|
|
145
|
+
)
|
|
146
|
+
structlogger.error(
|
|
147
|
+
"aws_persistor.ensure_bucket_exists.bucket_access_forbidden",
|
|
148
|
+
bucket_name=bucket_name,
|
|
149
|
+
event_info=log,
|
|
150
|
+
)
|
|
151
|
+
raise RasaException(log)
|
|
152
|
+
elif error_code == 404:
|
|
153
|
+
log = (
|
|
154
|
+
f"The specified bucket '{bucket_name}' does not exist. "
|
|
155
|
+
"Please make sure to create the bucket first."
|
|
156
|
+
)
|
|
157
|
+
structlogger.error(
|
|
158
|
+
"aws_persistor.ensure_bucket_exists.bucket_not_found",
|
|
159
|
+
bucket_name=bucket_name,
|
|
160
|
+
event_info=log,
|
|
161
|
+
)
|
|
162
|
+
raise RasaException(log)
|
|
146
163
|
|
|
147
164
|
def _persist_tar(self, file_key: Text, tar_path: Text) -> None:
|
|
148
165
|
"""Uploads a model persisted in the `target_dir` to s3."""
|
|
@@ -180,10 +197,30 @@ class GCSPersistor(Persistor):
|
|
|
180
197
|
from google.cloud import exceptions
|
|
181
198
|
|
|
182
199
|
try:
|
|
183
|
-
self.storage_client.
|
|
184
|
-
except exceptions.
|
|
185
|
-
|
|
186
|
-
|
|
200
|
+
self.storage_client.get_bucket(bucket_name)
|
|
201
|
+
except exceptions.NotFound:
|
|
202
|
+
log = (
|
|
203
|
+
f"The specified bucket '{bucket_name}' does not exist. "
|
|
204
|
+
"Please make sure to create the bucket first."
|
|
205
|
+
)
|
|
206
|
+
structlogger.error(
|
|
207
|
+
"gcp_persistor.ensure_bucket_exists.bucket_not_found",
|
|
208
|
+
bucket_name=bucket_name,
|
|
209
|
+
event_info=log,
|
|
210
|
+
)
|
|
211
|
+
raise RasaException(log)
|
|
212
|
+
except exceptions.Forbidden:
|
|
213
|
+
log = (
|
|
214
|
+
f"Access to the specified bucket '{bucket_name}' is forbidden. "
|
|
215
|
+
"Please make sure you have the necessary "
|
|
216
|
+
"permission to access the bucket. "
|
|
217
|
+
)
|
|
218
|
+
structlogger.error(
|
|
219
|
+
"gcp_persistor.ensure_bucket_exists.bucket_access_forbidden",
|
|
220
|
+
bucket_name=bucket_name,
|
|
221
|
+
event_info=log,
|
|
222
|
+
)
|
|
223
|
+
raise RasaException(log)
|
|
187
224
|
|
|
188
225
|
def _persist_tar(self, file_key: Text, tar_path: Text) -> None:
|
|
189
226
|
"""Uploads a model persisted in the `target_dir` to GCS."""
|
|
@@ -210,18 +247,23 @@ class AzurePersistor(Persistor):
|
|
|
210
247
|
account_url=f"https://{azure_account_name}.blob.core.windows.net/",
|
|
211
248
|
credential=azure_account_key,
|
|
212
249
|
)
|
|
213
|
-
|
|
214
|
-
self._ensure_container_exists(azure_container)
|
|
215
250
|
self.container_name = azure_container
|
|
251
|
+
self._ensure_container_exists()
|
|
216
252
|
|
|
217
|
-
def _ensure_container_exists(self
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
try:
|
|
221
|
-
self.blob_service.create_container(container_name)
|
|
222
|
-
except ResourceExistsError:
|
|
223
|
-
# no need to create the container, it already exists
|
|
253
|
+
def _ensure_container_exists(self) -> None:
|
|
254
|
+
if self._container_client().exists():
|
|
224
255
|
pass
|
|
256
|
+
else:
|
|
257
|
+
log = (
|
|
258
|
+
f"The specified container '{self.container_name}' does not exist."
|
|
259
|
+
"Please make sure to create the container first."
|
|
260
|
+
)
|
|
261
|
+
structlogger.error(
|
|
262
|
+
"azure_persistor.ensure_container_exists.container_not_found",
|
|
263
|
+
container_name=self.container_name,
|
|
264
|
+
event_info=log,
|
|
265
|
+
)
|
|
266
|
+
raise RasaException(log)
|
|
225
267
|
|
|
226
268
|
def _container_client(self) -> "ContainerClient":
|
|
227
269
|
return self.blob_service.get_container_client(self.container_name)
|
|
@@ -430,9 +430,9 @@ class ResponseSelector(DIETClassifier):
|
|
|
430
430
|
self, message: Message, prediction_dict: Dict[Text, Any], selector_key: Text
|
|
431
431
|
) -> None:
|
|
432
432
|
message_selector_properties = message.get(RESPONSE_SELECTOR_PROPERTY_NAME, {})
|
|
433
|
-
message_selector_properties[
|
|
434
|
-
|
|
435
|
-
|
|
433
|
+
message_selector_properties[RESPONSE_SELECTOR_RETRIEVAL_INTENTS] = (
|
|
434
|
+
self.all_retrieval_intents
|
|
435
|
+
)
|
|
436
436
|
message_selector_properties[selector_key] = prediction_dict
|
|
437
437
|
message.set(
|
|
438
438
|
RESPONSE_SELECTOR_PROPERTY_NAME,
|
|
@@ -505,7 +505,6 @@ class ResponseSelector(DIETClassifier):
|
|
|
505
505
|
been caught earlier and a warning should have been raised.
|
|
506
506
|
"""
|
|
507
507
|
for key, responses in self.responses.items():
|
|
508
|
-
|
|
509
508
|
# First check if the predicted label was the key itself
|
|
510
509
|
search_key = util.template_key_to_intent_response_key(key)
|
|
511
510
|
if search_key == label.get("name"):
|
|
@@ -626,7 +625,6 @@ class ResponseSelector(DIETClassifier):
|
|
|
626
625
|
config: Dict[Text, Any],
|
|
627
626
|
finetune_mode: bool = False,
|
|
628
627
|
) -> "RasaModel":
|
|
629
|
-
|
|
630
628
|
predict_data_example = RasaModelData(
|
|
631
629
|
label_key=model_data_example.label_key,
|
|
632
630
|
data={
|
|
@@ -723,7 +721,6 @@ class DIET2BOW(DIET):
|
|
|
723
721
|
logger.debug(f" {metric} ({name})")
|
|
724
722
|
|
|
725
723
|
def _update_label_metrics(self, loss: tf.Tensor, acc: tf.Tensor) -> None:
|
|
726
|
-
|
|
727
724
|
self.response_loss.update_state(loss)
|
|
728
725
|
self.response_acc.update_state(acc)
|
|
729
726
|
|
|
@@ -796,10 +793,10 @@ class DIET2DIET(DIET):
|
|
|
796
793
|
(self.text_name, self.config),
|
|
797
794
|
(self.label_name, label_config),
|
|
798
795
|
]:
|
|
799
|
-
self._tf_layers[
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
796
|
+
self._tf_layers[f"sequence_layer.{attribute}"] = (
|
|
797
|
+
rasa_layers.RasaSequenceLayer(
|
|
798
|
+
attribute, self.data_signature[attribute], config
|
|
799
|
+
)
|
|
803
800
|
)
|
|
804
801
|
|
|
805
802
|
if self.config[MASKED_LM]:
|
rasa/nlu/test.py
CHANGED
|
@@ -886,7 +886,6 @@ def evaluate_entities(
|
|
|
886
886
|
exclude_label=NO_ENTITY,
|
|
887
887
|
)
|
|
888
888
|
if output_directory:
|
|
889
|
-
|
|
890
889
|
_dump_report(output_directory, f"{extractor}_report.json", report)
|
|
891
890
|
|
|
892
891
|
if successes:
|
|
@@ -1550,7 +1549,6 @@ async def combine_result(
|
|
|
1550
1549
|
|
|
1551
1550
|
|
|
1552
1551
|
def _contains_entity_labels(entity_results: List[EntityEvaluationResult]) -> bool:
|
|
1553
|
-
|
|
1554
1552
|
for result in entity_results:
|
|
1555
1553
|
if result.entity_targets or result.entity_predictions:
|
|
1556
1554
|
return True
|
|
@@ -1791,7 +1789,6 @@ async def compare_nlu(
|
|
|
1791
1789
|
training_examples_per_run = []
|
|
1792
1790
|
|
|
1793
1791
|
for run in range(runs):
|
|
1794
|
-
|
|
1795
1792
|
logger.info("Beginning comparison run {}/{}".format(run + 1, runs))
|
|
1796
1793
|
|
|
1797
1794
|
run_path = os.path.join(output, "run_{}".format(run + 1))
|
|
@@ -25,7 +25,7 @@ from transformers import ( # noqa: E402
|
|
|
25
25
|
RobertaTokenizer,
|
|
26
26
|
CamembertTokenizer,
|
|
27
27
|
)
|
|
28
|
-
from rasa.nlu.utils.hugging_face.transformers_pre_post_processors import ( # noqa: E402
|
|
28
|
+
from rasa.nlu.utils.hugging_face.transformers_pre_post_processors import ( # noqa: E402
|
|
29
29
|
bert_tokens_pre_processor,
|
|
30
30
|
gpt_tokens_pre_processor,
|
|
31
31
|
xlnet_tokens_pre_processor,
|
rasa/nlu/utils/spacy_utils.py
CHANGED
|
@@ -195,7 +195,7 @@ class SpacyNLP(GraphComponent):
|
|
|
195
195
|
|
|
196
196
|
@staticmethod
|
|
197
197
|
def _filter_training_samples_by_content(
|
|
198
|
-
indexed_training_samples: List[Tuple[int, Text]]
|
|
198
|
+
indexed_training_samples: List[Tuple[int, Text]],
|
|
199
199
|
) -> Tuple[List[Tuple[int, Text]], List[Tuple[int, Text]]]:
|
|
200
200
|
"""Separates empty training samples from content bearing ones."""
|
|
201
201
|
docs_to_pipe = list(
|
|
@@ -251,7 +251,6 @@ class SpacyNLP(GraphComponent):
|
|
|
251
251
|
) -> Dict[Text, List[Any]]:
|
|
252
252
|
attribute_docs = {}
|
|
253
253
|
for attribute in DENSE_FEATURIZABLE_ATTRIBUTES:
|
|
254
|
-
|
|
255
254
|
texts = [
|
|
256
255
|
self._get_text(e, attribute) for e in training_data.training_examples
|
|
257
256
|
]
|
|
@@ -288,7 +287,6 @@ class SpacyNLP(GraphComponent):
|
|
|
288
287
|
attribute_docs = self._docs_for_training_data(model.model, training_data)
|
|
289
288
|
|
|
290
289
|
for attribute in DENSE_FEATURIZABLE_ATTRIBUTES:
|
|
291
|
-
|
|
292
290
|
for idx, example in enumerate(training_data.training_examples):
|
|
293
291
|
example_attribute_doc = attribute_docs[attribute][idx]
|
|
294
292
|
if len(example_attribute_doc):
|
rasa/server.py
CHANGED
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
import multiprocessing
|
|
5
5
|
import os
|
|
6
6
|
import traceback
|
|
7
|
+
import warnings
|
|
7
8
|
from collections import defaultdict
|
|
8
9
|
from functools import reduce, wraps
|
|
9
10
|
from http import HTTPStatus
|
|
@@ -25,6 +26,12 @@ from typing import (
|
|
|
25
26
|
|
|
26
27
|
import aiohttp
|
|
27
28
|
import jsonschema
|
|
29
|
+
from sanic import Sanic, response
|
|
30
|
+
from sanic.request import Request
|
|
31
|
+
from sanic.response import HTTPResponse
|
|
32
|
+
from sanic_cors import CORS
|
|
33
|
+
from sanic_jwt import Initialize, exceptions
|
|
34
|
+
|
|
28
35
|
import rasa
|
|
29
36
|
import rasa.core.utils
|
|
30
37
|
import rasa.nlu.test
|
|
@@ -70,11 +77,6 @@ from rasa.shared.utils.schemas.events import EVENTS_SCHEMA
|
|
|
70
77
|
from rasa.shared.utils.yaml import validate_training_data
|
|
71
78
|
from rasa.utils.common import TempDirectoryPath, get_temp_dir_name
|
|
72
79
|
from rasa.utils.endpoints import EndpointConfig
|
|
73
|
-
from sanic import Sanic, response
|
|
74
|
-
from sanic.request import Request
|
|
75
|
-
from sanic.response import HTTPResponse
|
|
76
|
-
from sanic_cors import CORS
|
|
77
|
-
from sanic_jwt import Initialize, exceptions
|
|
78
80
|
|
|
79
81
|
if TYPE_CHECKING:
|
|
80
82
|
from ssl import SSLContext
|
|
@@ -233,7 +235,6 @@ def requires_auth(
|
|
|
233
235
|
async def decorated(
|
|
234
236
|
request: Request, *args: Any, **kwargs: Any
|
|
235
237
|
) -> response.HTTPResponse:
|
|
236
|
-
|
|
237
238
|
provided = request.args.get("token", None)
|
|
238
239
|
|
|
239
240
|
# noinspection PyProtectedMember
|
|
@@ -518,7 +519,18 @@ def add_root_route(app: Sanic) -> None:
|
|
|
518
519
|
@app.get("/")
|
|
519
520
|
async def hello(request: Request) -> HTTPResponse:
|
|
520
521
|
"""Check if the server is running and responds with the version."""
|
|
521
|
-
|
|
522
|
+
html_content = f"""
|
|
523
|
+
<html>
|
|
524
|
+
<body>
|
|
525
|
+
<p>Hello from Rasa: {rasa.__version__}</p>
|
|
526
|
+
<a href="./webhooks/inspector/inspect.html">Go to the inspector</a>
|
|
527
|
+
<script>
|
|
528
|
+
window.location.replace("./webhooks/inspector/inspect.html");
|
|
529
|
+
</script>
|
|
530
|
+
</body>
|
|
531
|
+
</html>
|
|
532
|
+
"""
|
|
533
|
+
return response.html(html_content)
|
|
522
534
|
|
|
523
535
|
|
|
524
536
|
def async_if_callback_url(f: Callable[..., Coroutine]) -> Callable:
|
|
@@ -647,6 +659,9 @@ def create_app(
|
|
|
647
659
|
app.config.RESPONSE_TIMEOUT = response_timeout
|
|
648
660
|
configure_cors(app, cors_origins)
|
|
649
661
|
|
|
662
|
+
# Reset Sanic warnings filter that allows the triggering of Sanic warnings
|
|
663
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning, module=r"sanic.*")
|
|
664
|
+
|
|
650
665
|
# Set up the Sanic-JWT extension
|
|
651
666
|
if jwt_secret and jwt_method:
|
|
652
667
|
# `sanic-jwt` depends on having an available event loop when making the call to
|
rasa/shared/constants.py
CHANGED
|
@@ -17,6 +17,7 @@ DOCS_URL_COMPONENTS = DOCS_URL_CONCEPTS + "/components/overview"
|
|
|
17
17
|
DOCS_URL_GRAPH_COMPONENTS = DOCS_URL_CONCEPTS + "/components/custom-graph-components"
|
|
18
18
|
DOCS_URL_GRAPH_RECIPE = DOCS_URL_CONCEPTS + "/components/graph-recipe"
|
|
19
19
|
DOCS_URL_CATEGORICAL_SLOTS = DOCS_URL_CONCEPTS + "/domain#categorical-slot"
|
|
20
|
+
DOCS_URL_DOMAIN = DOCS_URL_CONCEPTS + "/domain"
|
|
20
21
|
|
|
21
22
|
# Docs URLs for NLU-based assistants
|
|
22
23
|
DOCS_URL_TRAINING_DATA = DOCS_URL_NLU_BASED + "/training-data-format"
|
|
@@ -77,6 +78,8 @@ DEFAULT_LOG_LEVEL_LLM = "DEBUG"
|
|
|
77
78
|
ENV_LOG_LEVEL_LLM = "LOG_LEVEL_LLM"
|
|
78
79
|
ENV_LOG_LEVEL_LLM_MODULE_NAMES = {
|
|
79
80
|
"LLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
81
|
+
"SingleStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
82
|
+
"MultiStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
80
83
|
"EnterpriseSearchPolicy": "LOG_LEVEL_LLM_ENTERPRISE_SEARCH",
|
|
81
84
|
"IntentlessPolicy": "LOG_LEVEL_LLM_INTENTLESS_POLICY",
|
|
82
85
|
"ContextualResponseRephraser": "LOG_LEVEL_LLM_REPHRASER",
|
|
@@ -109,7 +112,7 @@ CONFIG_MANDATORY_KEYS = CONFIG_MANDATORY_KEYS_CORE + CONFIG_MANDATORY_KEYS_NLU
|
|
|
109
112
|
REQUIRED_SLOTS_KEY = "required_slots"
|
|
110
113
|
IGNORED_INTENTS = "ignored_intents"
|
|
111
114
|
|
|
112
|
-
# Constants for default Rasa
|
|
115
|
+
# Constants for default Rasa Pro project layout
|
|
113
116
|
DEFAULT_ENDPOINTS_PATH = "endpoints.yml"
|
|
114
117
|
DEFAULT_CREDENTIALS_PATH = "credentials.yml"
|
|
115
118
|
DEFAULT_CONFIG_PATH = "config.yml"
|
|
@@ -174,8 +177,16 @@ RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_EMPTY = (
|
|
|
174
177
|
RASA_PATTERN_CANNOT_HANDLE_PREFIX = "cannot_handle_"
|
|
175
178
|
RASA_PATTERN_CANNOT_HANDLE_DEFAULT = RASA_PATTERN_CANNOT_HANDLE_PREFIX + "default"
|
|
176
179
|
RASA_PATTERN_CANNOT_HANDLE_CHITCHAT = RASA_PATTERN_CANNOT_HANDLE_PREFIX + "chitchat"
|
|
180
|
+
RASA_PATTERN_CANNOT_HANDLE_NOT_SUPPORTED = (
|
|
181
|
+
RASA_PATTERN_CANNOT_HANDLE_PREFIX + "not_supported"
|
|
182
|
+
)
|
|
177
183
|
RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT = (
|
|
178
184
|
RASA_PATTERN_CANNOT_HANDLE_PREFIX + "invalid_intent"
|
|
179
185
|
)
|
|
180
186
|
|
|
181
187
|
ROUTE_TO_CALM_SLOT = "route_session_to_calm"
|
|
188
|
+
EMBEDDINGS_CONFIG_KEY = "embeddings"
|
|
189
|
+
MODEL_CONFIG_KEY = "model"
|
|
190
|
+
MODEL_NAME_CONFIG_KEY = "model_name"
|
|
191
|
+
PROMPT_CONFIG_KEY = "prompt"
|
|
192
|
+
PROMPT_TEMPLATE_CONFIG_KEY = "prompt_template"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import re
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from rasa.dialogue_understanding.commands.set_slot_command import SetSlotExtractor
|
|
8
|
+
from rasa.shared.core.domain import Domain
|
|
9
|
+
from rasa.shared.nlu.constants import COMMANDS, SET_SLOT_COMMAND, TEXT
|
|
10
|
+
from rasa.shared.nlu.training_data.message import Message
|
|
11
|
+
|
|
12
|
+
structlogger = structlog.get_logger()
|
|
13
|
+
|
|
14
|
+
SET_SLOTS_PATTERN = r"(?P<slot_name>[^(),=]+)=(?P<slot_value>[^(),]+)"
|
|
15
|
+
MAX_NUMBER_OF_SLOTS = 10
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CommandPayloadReader:
|
|
19
|
+
@staticmethod
|
|
20
|
+
def unpack_regex_message(
|
|
21
|
+
message: Message,
|
|
22
|
+
domain: Optional[Domain] = None,
|
|
23
|
+
entity_extractor_name: Optional[
|
|
24
|
+
str
|
|
25
|
+
] = SetSlotExtractor.COMMAND_PAYLOAD_READER.value,
|
|
26
|
+
) -> Message:
|
|
27
|
+
"""Extracts commands from user text and adds them to the message."""
|
|
28
|
+
user_text = message.get(TEXT).strip()
|
|
29
|
+
|
|
30
|
+
# prevent ReDos attacks by placing a limit on the number of slots
|
|
31
|
+
if CommandPayloadReader.is_above_slot_limit(user_text):
|
|
32
|
+
return message
|
|
33
|
+
|
|
34
|
+
matches = CommandPayloadReader.find_matches(user_text)
|
|
35
|
+
if not matches:
|
|
36
|
+
structlogger.warning(
|
|
37
|
+
"message.parsing.failed", user_text=copy.deepcopy(user_text)
|
|
38
|
+
)
|
|
39
|
+
return message
|
|
40
|
+
|
|
41
|
+
return CommandPayloadReader.extract_commands_from_pattern_matches(
|
|
42
|
+
message, matches, domain, entity_extractor_name
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def find_matches(user_text: str) -> List[re.Match]:
|
|
47
|
+
return re.findall(SET_SLOTS_PATTERN, user_text)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def extract_commands_from_pattern_matches(
|
|
51
|
+
message: Message,
|
|
52
|
+
matches: List[re.Match],
|
|
53
|
+
domain: Optional[Domain] = None,
|
|
54
|
+
entity_extractor_name: Optional[
|
|
55
|
+
str
|
|
56
|
+
] = SetSlotExtractor.COMMAND_PAYLOAD_READER.value,
|
|
57
|
+
) -> Message:
|
|
58
|
+
"""Extract attributes from the matches and validate them via the domain."""
|
|
59
|
+
commands = []
|
|
60
|
+
|
|
61
|
+
for match in matches:
|
|
62
|
+
slot_name = match[0].strip()
|
|
63
|
+
slot_value = match[1].strip()
|
|
64
|
+
|
|
65
|
+
domain_slot_names = [slot.name for slot in domain.slots] if domain else []
|
|
66
|
+
|
|
67
|
+
if domain and slot_name not in domain_slot_names:
|
|
68
|
+
structlogger.warning(
|
|
69
|
+
"slot.not.found",
|
|
70
|
+
slot_name=slot_name,
|
|
71
|
+
)
|
|
72
|
+
return message
|
|
73
|
+
|
|
74
|
+
slot_value = (
|
|
75
|
+
slot_value
|
|
76
|
+
if slot_value.lower() not in {"none", "null", "undefined"}
|
|
77
|
+
else None
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Create new SetSlot commands from the extracted attributes.
|
|
81
|
+
commands.append(
|
|
82
|
+
{
|
|
83
|
+
"command": SET_SLOT_COMMAND,
|
|
84
|
+
"name": slot_name,
|
|
85
|
+
"value": slot_value,
|
|
86
|
+
"extractor": entity_extractor_name,
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
structlogger.debug(
|
|
91
|
+
"slot.set.command.added",
|
|
92
|
+
slot_name=slot_name,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# set the command(s) on the Message object
|
|
96
|
+
message.set(COMMANDS, commands, add_to_output=True)
|
|
97
|
+
return message
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def is_above_slot_limit(user_text: str) -> bool:
|
|
101
|
+
"""Prevent ReDoS attacks by limiting the number of slots."""
|
|
102
|
+
if user_text.count("=") > MAX_NUMBER_OF_SLOTS:
|
|
103
|
+
structlogger.warning(
|
|
104
|
+
"too.many.slots",
|
|
105
|
+
user_text=copy.deepcopy(user_text),
|
|
106
|
+
slot_limit=10,
|
|
107
|
+
)
|
|
108
|
+
return True
|
|
109
|
+
return False
|
rasa/shared/core/constants.py
CHANGED
|
@@ -85,6 +85,7 @@ LOOP_INTERRUPTED = "is_interrupted"
|
|
|
85
85
|
LOOP_REJECTED = "rejected"
|
|
86
86
|
TRIGGER_MESSAGE = "trigger_message"
|
|
87
87
|
FOLLOWUP_ACTION = "followup_action"
|
|
88
|
+
ACTIVE_FLOW = "active_flow"
|
|
88
89
|
|
|
89
90
|
# start of special user message section
|
|
90
91
|
EXTERNAL_MESSAGE_PREFIX = "EXTERNAL: "
|
|
@@ -130,6 +131,7 @@ class SlotMappingType(Enum):
|
|
|
130
131
|
FROM_INTENT = "from_intent"
|
|
131
132
|
FROM_TRIGGER_INTENT = "from_trigger_intent"
|
|
132
133
|
FROM_TEXT = "from_text"
|
|
134
|
+
FROM_LLM = "from_llm"
|
|
133
135
|
CUSTOM = "custom"
|
|
134
136
|
|
|
135
137
|
def __str__(self) -> str:
|
|
@@ -137,11 +139,8 @@ class SlotMappingType(Enum):
|
|
|
137
139
|
return self.value
|
|
138
140
|
|
|
139
141
|
def is_predefined_type(self) -> bool:
|
|
140
|
-
"""Returns True
|
|
141
|
-
|
|
142
|
-
That is, to evaluate the mapping no custom action execution is needed.
|
|
143
|
-
"""
|
|
144
|
-
return self != SlotMappingType.CUSTOM
|
|
142
|
+
"""Returns True if the mapping type is NLU-predefined."""
|
|
143
|
+
return not (self == SlotMappingType.CUSTOM or self == SlotMappingType.FROM_LLM)
|
|
145
144
|
|
|
146
145
|
|
|
147
146
|
# the keys for `State` (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
|