rasa-pro 3.11.0__py3-none-any.whl → 3.11.0a2__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 +396 -17
- rasa/__main__.py +15 -31
- rasa/api.py +1 -5
- rasa/cli/arguments/default_arguments.py +2 -1
- rasa/cli/arguments/shell.py +1 -5
- rasa/cli/arguments/train.py +0 -14
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +8 -8
- rasa/cli/inspect.py +5 -7
- rasa/cli/interactive.py +0 -1
- rasa/cli/llm_fine_tuning.py +1 -1
- rasa/cli/project_templates/calm/config.yml +7 -5
- rasa/cli/project_templates/calm/endpoints.yml +2 -15
- rasa/cli/project_templates/tutorial/config.yml +5 -8
- rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +0 -5
- rasa/cli/project_templates/tutorial/domain.yml +0 -14
- rasa/cli/project_templates/tutorial/endpoints.yml +0 -5
- rasa/cli/run.py +1 -1
- rasa/cli/scaffold.py +2 -4
- rasa/cli/studio/studio.py +8 -18
- rasa/cli/studio/upload.py +15 -0
- rasa/cli/train.py +0 -3
- rasa/cli/utils.py +1 -6
- rasa/cli/x.py +8 -8
- rasa/constants.py +1 -3
- rasa/core/actions/action.py +33 -75
- rasa/core/actions/e2e_stub_custom_action_executor.py +1 -5
- rasa/core/actions/http_custom_action_executor.py +0 -4
- rasa/core/channels/channel.py +0 -20
- rasa/core/channels/development_inspector.py +2 -8
- rasa/core/channels/inspector/dist/assets/{arc-bc141fb2.js → arc-6852c607.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-be2db283.js → c4Diagram-d0fbc5ce-acc952b2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-55366915.js → classDiagram-936ed81e-848a7597.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-bb529518.js → classDiagram-v2-c3cb15f1-a73d3e68.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-b0ec81d6.js → createText-62fc7601-e5ee049d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-6166330c.js → edges-f2ad444c-771e517e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-5ccc6a8e.js → erDiagram-9d236eb7-aa347178.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-fca3bfe4.js → flowDb-1972c806-651fc57d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4739080f.js → flowDiagram-7ea5b25a-ca67804f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-587d82d8.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-7c1b0e0f.js → flowchart-elk-definition-abe16c3d-2dbc568d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-772fd050.js → ganttDiagram-9b5ea136-25a65bd8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-8eae1dc9.js → gitGraphDiagram-99d0ae7c-fdc7378d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-f55afcdf.js → index-2c4b9a3b-6f1fd606.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-e7cef9de.js → index-efdd30c1.js} +68 -68
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-124d4a14.js → infoDiagram-736b4530-cb1a041a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-7c4fae44.js → journeyDiagram-df861f2b-14609879.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-b9885fb6.js → layout-2490f52b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-7c59abb6.js → line-40186f1f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-4776f780.js → linear-08814e93.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2332c46c.js → mindmap-definition-beec6740-1a534584.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-8fb39303.js → pieDiagram-dbbf0591-72397b61.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-3c7180a2.js → quadrantDiagram-4d7f4fd6-3bb0b6a3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-e910bcb8.js → requirementDiagram-6fc4c22a-57334f61.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-ead16c89.js → sankeyDiagram-8f13d901-111e1297.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-29a02a19.js → sequenceDiagram-b655622a-10bcfe62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-042b3137.js → stateDiagram-59f0c015-acaf7513.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-2178c0f3.js → stateDiagram-v2-2b26beab-3ec2a235.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-23ffa4fc.js → styles-080da4f6-62730289.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-94f59763.js → styles-3dcbcfbf-5284ee76.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-78a6bebc.js → styles-9c745c82-642435e3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-eae2a6f6.js → svgDrawCommon-4835440b-b250a350.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-5c968d92.js → timeline-definition-5b62e21b-c2b147ed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-fd3db0d5.js → xychartDiagram-2b33534f-f92cfea9.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +1 -1
- rasa/core/channels/inspector/src/helpers/audiostream.ts +16 -77
- rasa/core/channels/socketio.py +2 -7
- rasa/core/channels/telegram.py +1 -1
- rasa/core/channels/twilio.py +1 -1
- rasa/core/channels/voice_ready/audiocodes.py +4 -15
- rasa/core/channels/voice_ready/jambonz.py +4 -15
- rasa/core/channels/voice_ready/twilio_voice.py +21 -6
- rasa/core/channels/voice_ready/utils.py +5 -6
- rasa/core/channels/voice_stream/asr/asr_engine.py +1 -19
- rasa/core/channels/voice_stream/asr/asr_event.py +0 -5
- rasa/core/channels/voice_stream/asr/deepgram.py +15 -28
- rasa/core/channels/voice_stream/audio_bytes.py +0 -1
- rasa/core/channels/voice_stream/browser_audio.py +9 -32
- rasa/core/channels/voice_stream/tts/azure.py +3 -9
- rasa/core/channels/voice_stream/tts/cartesia.py +8 -12
- rasa/core/channels/voice_stream/tts/tts_engine.py +1 -11
- rasa/core/channels/voice_stream/twilio_media_streams.py +19 -28
- rasa/core/channels/voice_stream/util.py +4 -4
- rasa/core/channels/voice_stream/voice_channel.py +42 -222
- rasa/core/featurizers/single_state_featurizer.py +1 -22
- rasa/core/featurizers/tracker_featurizers.py +18 -115
- rasa/core/information_retrieval/qdrant.py +0 -1
- rasa/core/nlg/contextual_response_rephraser.py +25 -44
- rasa/core/persistor.py +34 -191
- rasa/core/policies/enterprise_search_policy.py +60 -119
- rasa/core/policies/flows/flow_executor.py +4 -7
- rasa/core/policies/intentless_policy.py +22 -82
- rasa/core/policies/ted_policy.py +33 -58
- rasa/core/policies/unexpected_intent_policy.py +7 -15
- rasa/core/processor.py +5 -32
- rasa/core/training/interactive.py +35 -34
- rasa/core/utils.py +22 -58
- rasa/dialogue_understanding/coexistence/llm_based_router.py +12 -39
- rasa/dialogue_understanding/commands/__init__.py +0 -4
- rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
- rasa/dialogue_understanding/commands/utils.py +0 -5
- rasa/dialogue_understanding/generator/constants.py +0 -2
- rasa/dialogue_understanding/generator/flow_retrieval.py +4 -49
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +23 -37
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +10 -57
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -19
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +0 -3
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +10 -90
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +0 -53
- rasa/dialogue_understanding/processor/command_processor.py +1 -21
- rasa/e2e_test/assertions.py +16 -133
- rasa/e2e_test/assertions_schema.yml +0 -23
- rasa/e2e_test/e2e_test_case.py +6 -85
- rasa/e2e_test/e2e_test_runner.py +4 -6
- rasa/e2e_test/utils/io.py +1 -3
- rasa/engine/loader.py +0 -12
- rasa/engine/validation.py +11 -541
- rasa/keys +1 -0
- rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
- rasa/model_training.py +7 -29
- rasa/nlu/classifiers/diet_classifier.py +25 -38
- 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 +50 -93
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +16 -45
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
- rasa/nlu/tokenizers/whitespace_tokenizer.py +14 -3
- rasa/server.py +1 -3
- rasa/shared/constants.py +0 -61
- rasa/shared/core/constants.py +0 -9
- rasa/shared/core/domain.py +5 -8
- rasa/shared/core/flows/flow.py +0 -5
- rasa/shared/core/flows/flows_list.py +1 -5
- rasa/shared/core/flows/flows_yaml_schema.json +0 -10
- rasa/shared/core/flows/validation.py +0 -96
- rasa/shared/core/flows/yaml_flows_io.py +4 -13
- rasa/shared/core/slots.py +0 -5
- rasa/shared/importers/importer.py +2 -19
- rasa/shared/importers/rasa.py +1 -5
- rasa/shared/nlu/training_data/features.py +2 -120
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -18
- rasa/shared/providers/_configs/azure_openai_client_config.py +3 -5
- rasa/shared/providers/_configs/openai_client_config.py +1 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +0 -1
- rasa/shared/providers/_configs/utils.py +0 -16
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +29 -18
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +21 -54
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +0 -24
- rasa/shared/providers/llm/_base_litellm_client.py +31 -63
- rasa/shared/providers/llm/azure_openai_llm_client.py +29 -50
- rasa/shared/providers/llm/default_litellm_llm_client.py +0 -24
- rasa/shared/providers/llm/self_hosted_llm_client.py +29 -17
- rasa/shared/providers/mappings.py +0 -19
- rasa/shared/utils/common.py +2 -37
- rasa/shared/utils/io.py +6 -28
- rasa/shared/utils/llm.py +46 -353
- rasa/shared/utils/yaml.py +82 -181
- rasa/studio/auth.py +5 -3
- rasa/studio/config.py +4 -13
- rasa/studio/constants.py +0 -1
- rasa/studio/data_handler.py +4 -13
- rasa/studio/upload.py +80 -175
- rasa/telemetry.py +17 -94
- rasa/tracing/config.py +1 -3
- rasa/tracing/instrumentation/attribute_extractors.py +17 -94
- rasa/tracing/instrumentation/instrumentation.py +0 -121
- rasa/utils/common.py +0 -5
- rasa/utils/endpoints.py +1 -27
- rasa/utils/io.py +81 -7
- rasa/utils/log_utils.py +2 -9
- rasa/utils/tensorflow/model_data.py +193 -2
- rasa/validator.py +4 -110
- rasa/version.py +1 -1
- rasa_pro-3.11.0a2.dist-info/METADATA +576 -0
- {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/RECORD +181 -213
- rasa/core/actions/action_repeat_bot_messages.py +0 -89
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +0 -1
- rasa/core/channels/voice_stream/asr/azure.py +0 -129
- rasa/core/channels/voice_stream/call_state.py +0 -23
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +0 -60
- rasa/dialogue_understanding/commands/user_silence_command.py +0 -59
- rasa/dialogue_understanding/patterns/repeat.py +0 -37
- rasa/dialogue_understanding/patterns/user_silence.py +0 -37
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +0 -40
- rasa/model_manager/model_api.py +0 -559
- rasa/model_manager/runner_service.py +0 -286
- rasa/model_manager/socket_bridge.py +0 -146
- rasa/model_manager/studio_jwt_auth.py +0 -86
- rasa/model_manager/trainer_service.py +0 -325
- rasa/model_manager/utils.py +0 -87
- rasa/model_manager/warm_rasa_process.py +0 -187
- rasa/model_service.py +0 -112
- rasa/shared/core/flows/utils.py +0 -39
- rasa/shared/providers/_configs/litellm_router_client_config.py +0 -220
- rasa/shared/providers/_configs/model_group_config.py +0 -167
- rasa/shared/providers/_configs/rasa_llm_client_config.py +0 -73
- rasa/shared/providers/_utils.py +0 -79
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +0 -135
- rasa/shared/providers/llm/litellm_router_llm_client.py +0 -182
- rasa/shared/providers/llm/rasa_llm_client.py +0 -112
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +0 -183
- rasa/shared/providers/router/router_client.py +0 -73
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +0 -31
- rasa/shared/utils/health_check/health_check.py +0 -258
- rasa/shared/utils/health_check/llm_health_check_mixin.py +0 -31
- rasa/utils/sanic_error_handler.py +0 -32
- rasa/utils/tensorflow/feature_array.py +0 -366
- rasa_pro-3.11.0.dist-info/METADATA +0 -198
- {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/entry_points.txt +0 -0
rasa/utils/common.py
CHANGED
|
@@ -90,11 +90,6 @@ EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
|
|
|
90
90
|
# Ignore Keras DeprecationWarning since it requires that we
|
|
91
91
|
# upgrade tensorflow-macos to 2.13.0 version.
|
|
92
92
|
(DeprecationWarning, "invalid escape sequence*"),
|
|
93
|
-
# Ignore importlib open_text and read_text warnings for now
|
|
94
|
-
(
|
|
95
|
-
DeprecationWarning,
|
|
96
|
-
"https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy",
|
|
97
|
-
),
|
|
98
93
|
]
|
|
99
94
|
|
|
100
95
|
PYTHON_LOGGING_SCHEMA_DOCS = (
|
rasa/utils/endpoints.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import ssl
|
|
3
3
|
from types import ModuleType
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Optional, Text, Dict, Union
|
|
5
5
|
|
|
6
6
|
import aiohttp
|
|
7
7
|
import structlog
|
|
@@ -41,32 +41,6 @@ def read_endpoint_config(
|
|
|
41
41
|
return None
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def read_property_config_from_endpoints_file(
|
|
45
|
-
filename: str, property_name: str
|
|
46
|
-
) -> Optional[Union[Dict[str, Any], List]]:
|
|
47
|
-
"""Read a property from an endpoint configuration file."""
|
|
48
|
-
if not filename:
|
|
49
|
-
return None
|
|
50
|
-
|
|
51
|
-
try:
|
|
52
|
-
content = read_config_file(filename)
|
|
53
|
-
|
|
54
|
-
if content.get(property_name) is None:
|
|
55
|
-
return None
|
|
56
|
-
|
|
57
|
-
return content[property_name]
|
|
58
|
-
except FileNotFoundError:
|
|
59
|
-
structlogger.error(
|
|
60
|
-
"endpoint.read.failed_no_such_file",
|
|
61
|
-
filename=os.path.abspath(filename),
|
|
62
|
-
event_info=(
|
|
63
|
-
"Failed to read endpoint configuration file - "
|
|
64
|
-
"the file was not found."
|
|
65
|
-
),
|
|
66
|
-
)
|
|
67
|
-
return None
|
|
68
|
-
|
|
69
|
-
|
|
70
44
|
def concat_url(base: Text, subpath: Optional[Text]) -> Text:
|
|
71
45
|
"""Append a subpath to a base url.
|
|
72
46
|
|
rasa/utils/io.py
CHANGED
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import filecmp
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
|
+
import pickle
|
|
5
6
|
import tempfile
|
|
6
7
|
import warnings
|
|
7
8
|
import re
|
|
@@ -18,6 +19,7 @@ from typing import (
|
|
|
18
19
|
Type,
|
|
19
20
|
Callable,
|
|
20
21
|
TYPE_CHECKING,
|
|
22
|
+
Pattern,
|
|
21
23
|
)
|
|
22
24
|
|
|
23
25
|
from ruamel import yaml
|
|
@@ -96,6 +98,29 @@ def enable_async_loop_debugging(
|
|
|
96
98
|
return event_loop
|
|
97
99
|
|
|
98
100
|
|
|
101
|
+
def pickle_dump(filename: Union[Text, Path], obj: Any) -> None:
|
|
102
|
+
"""Saves object to file.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
filename: the filename to save the object to
|
|
106
|
+
obj: the object to store
|
|
107
|
+
"""
|
|
108
|
+
with open(filename, "wb") as f:
|
|
109
|
+
pickle.dump(obj, f)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def pickle_load(filename: Union[Text, Path]) -> Any:
|
|
113
|
+
"""Loads an object from a file.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
filename: the filename to load the object from
|
|
117
|
+
|
|
118
|
+
Returns: the loaded object
|
|
119
|
+
"""
|
|
120
|
+
with open(filename, "rb") as f:
|
|
121
|
+
return pickle.load(f)
|
|
122
|
+
|
|
123
|
+
|
|
99
124
|
def create_temporary_file(data: Any, suffix: Text = "", mode: Text = "w+") -> Text:
|
|
100
125
|
"""Creates a tempfile.NamedTemporaryFile object for data."""
|
|
101
126
|
encoding = None if "b" in mode else rasa.shared.utils.io.DEFAULT_ENCODING
|
|
@@ -166,14 +191,63 @@ def create_validator(
|
|
|
166
191
|
return FunctionValidator
|
|
167
192
|
|
|
168
193
|
|
|
169
|
-
def
|
|
170
|
-
|
|
194
|
+
def json_unpickle(
|
|
195
|
+
file_name: Union[Text, Path], encode_non_string_keys: bool = False
|
|
196
|
+
) -> Any:
|
|
197
|
+
"""Unpickle an object from file using json.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
file_name: the file to load the object from
|
|
201
|
+
encode_non_string_keys: If set to `True` then jsonpickle will encode non-string
|
|
202
|
+
dictionary keys instead of coercing them into strings via `repr()`.
|
|
203
|
+
|
|
204
|
+
Returns: the object
|
|
205
|
+
"""
|
|
206
|
+
import jsonpickle.ext.numpy as jsonpickle_numpy
|
|
207
|
+
import jsonpickle
|
|
208
|
+
|
|
209
|
+
jsonpickle_numpy.register_handlers()
|
|
210
|
+
|
|
211
|
+
file_content = rasa.shared.utils.io.read_file(file_name)
|
|
212
|
+
return jsonpickle.loads(file_content, keys=encode_non_string_keys)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def json_pickle(
|
|
216
|
+
file_name: Union[Text, Path], obj: Any, encode_non_string_keys: bool = False
|
|
217
|
+
) -> None:
|
|
218
|
+
"""Pickle an object to a file using json.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
file_name: the file to store the object to
|
|
222
|
+
obj: the object to store
|
|
223
|
+
encode_non_string_keys: If set to `True` then jsonpickle will encode non-string
|
|
224
|
+
dictionary keys instead of coercing them into strings via `repr()`.
|
|
225
|
+
"""
|
|
226
|
+
import jsonpickle.ext.numpy as jsonpickle_numpy
|
|
227
|
+
import jsonpickle
|
|
228
|
+
|
|
229
|
+
jsonpickle_numpy.register_handlers()
|
|
171
230
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
231
|
+
rasa.shared.utils.io.write_text_file(
|
|
232
|
+
jsonpickle.dumps(obj, keys=encode_non_string_keys), file_name
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def get_emoji_regex() -> Pattern:
|
|
237
|
+
"""Returns regex to identify emojis."""
|
|
238
|
+
return re.compile(
|
|
239
|
+
"["
|
|
240
|
+
"\U0001f600-\U0001f64f" # emoticons
|
|
241
|
+
"\U0001f300-\U0001f5ff" # symbols & pictographs
|
|
242
|
+
"\U0001f680-\U0001f6ff" # transport & map symbols
|
|
243
|
+
"\U0001f1e0-\U0001f1ff" # flags (iOS)
|
|
244
|
+
"\U00002702-\U000027b0"
|
|
245
|
+
"\U000024c2-\U0001f251"
|
|
246
|
+
"\u200d" # zero width joiner
|
|
247
|
+
"\u200c" # zero width non-joiner
|
|
248
|
+
"]+",
|
|
249
|
+
flags=re.UNICODE,
|
|
250
|
+
)
|
|
177
251
|
|
|
178
252
|
|
|
179
253
|
def are_directories_equal(dir1: Path, dir2: Path) -> bool:
|
rasa/utils/log_utils.py
CHANGED
|
@@ -78,7 +78,6 @@ def _anonymizer(
|
|
|
78
78
|
|
|
79
79
|
def configure_structlog(
|
|
80
80
|
log_level: Optional[int] = None,
|
|
81
|
-
include_time: bool = False,
|
|
82
81
|
) -> None:
|
|
83
82
|
"""Configure logging of the server."""
|
|
84
83
|
if log_level is None: # Log level NOTSET is 0 so we use `is None` here
|
|
@@ -115,9 +114,6 @@ def configure_structlog(
|
|
|
115
114
|
SentryProcessor(event_level=logging.FATAL),
|
|
116
115
|
]
|
|
117
116
|
|
|
118
|
-
if include_time:
|
|
119
|
-
shared_processors.append(structlog.processors.TimeStamper(fmt="iso"))
|
|
120
|
-
|
|
121
117
|
if not FORCE_JSON_LOGGING and sys.stderr.isatty():
|
|
122
118
|
# Pretty printing when we run in a terminal session.
|
|
123
119
|
# Automatically prints pretty tracebacks when "rich" is installed
|
|
@@ -147,14 +143,11 @@ def configure_structlog(
|
|
|
147
143
|
# logger.
|
|
148
144
|
cache_logger_on_first_use=True,
|
|
149
145
|
)
|
|
150
|
-
# doing logger creation inline, to prevent usage of unconfigured logger
|
|
151
|
-
structlog.get_logger().debug("structlog.configured")
|
|
152
146
|
|
|
153
147
|
|
|
154
148
|
def log_llm(logger: Any, log_module: str, log_event: str, **kwargs: Any) -> None:
|
|
155
|
-
"""Logs LLM-specific events depending on a flag passed through an
|
|
156
|
-
|
|
157
|
-
If the module's flag is set to INFO (e.g.
|
|
149
|
+
"""Logs LLM-specific events depending on a flag passed through an environment
|
|
150
|
+
variable. If the module's flag is set to INFO (e.g.
|
|
158
151
|
LOG_PROMPT_LLM_COMMAND_GENERATOR=INFO), its prompt is logged at INFO level,
|
|
159
152
|
overriding the general log level setting.
|
|
160
153
|
|
|
@@ -20,8 +20,6 @@ import numpy as np
|
|
|
20
20
|
import scipy.sparse
|
|
21
21
|
from sklearn.model_selection import train_test_split
|
|
22
22
|
|
|
23
|
-
from rasa.utils.tensorflow.feature_array import FeatureArray
|
|
24
|
-
|
|
25
23
|
logger = logging.getLogger(__name__)
|
|
26
24
|
|
|
27
25
|
|
|
@@ -39,6 +37,199 @@ def ragged_array_to_ndarray(ragged_array: Iterable[np.ndarray]) -> np.ndarray:
|
|
|
39
37
|
return np.array(ragged_array, dtype=object)
|
|
40
38
|
|
|
41
39
|
|
|
40
|
+
class FeatureArray(np.ndarray):
|
|
41
|
+
"""Stores any kind of features ready to be used by a RasaModel.
|
|
42
|
+
|
|
43
|
+
Next to the input numpy array of features, it also received the number of
|
|
44
|
+
dimensions of the features.
|
|
45
|
+
As our features can have 1 to 4 dimensions we might have different number of numpy
|
|
46
|
+
arrays stacked. The number of dimensions helps us to figure out how to handle this
|
|
47
|
+
particular feature array. Also, it is automatically determined whether the feature
|
|
48
|
+
array is sparse or not and the number of units is determined as well.
|
|
49
|
+
|
|
50
|
+
Subclassing np.array: https://numpy.org/doc/stable/user/basics.subclassing.html
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __new__(
|
|
54
|
+
cls, input_array: np.ndarray, number_of_dimensions: int
|
|
55
|
+
) -> "FeatureArray":
|
|
56
|
+
"""Create and return a new object. See help(type) for accurate signature."""
|
|
57
|
+
FeatureArray._validate_number_of_dimensions(number_of_dimensions, input_array)
|
|
58
|
+
|
|
59
|
+
feature_array = np.asarray(input_array).view(cls)
|
|
60
|
+
|
|
61
|
+
if number_of_dimensions <= 2:
|
|
62
|
+
feature_array.units = input_array.shape[-1]
|
|
63
|
+
feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
|
|
64
|
+
elif number_of_dimensions == 3:
|
|
65
|
+
feature_array.units = input_array[0].shape[-1]
|
|
66
|
+
feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
|
|
67
|
+
elif number_of_dimensions == 4:
|
|
68
|
+
feature_array.units = input_array[0][0].shape[-1]
|
|
69
|
+
feature_array.is_sparse = isinstance(
|
|
70
|
+
input_array[0][0], scipy.sparse.spmatrix
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"Number of dimensions '{number_of_dimensions}' currently not "
|
|
75
|
+
f"supported."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
feature_array.number_of_dimensions = number_of_dimensions
|
|
79
|
+
|
|
80
|
+
return feature_array
|
|
81
|
+
|
|
82
|
+
def __init__(
|
|
83
|
+
self, input_array: Any, number_of_dimensions: int, **kwargs: Any
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Initialize. FeatureArray.
|
|
86
|
+
|
|
87
|
+
Needed in order to avoid 'Invalid keyword argument number_of_dimensions
|
|
88
|
+
to function FeatureArray.__init__ '
|
|
89
|
+
Args:
|
|
90
|
+
input_array: the array that contains features
|
|
91
|
+
number_of_dimensions: number of dimensions in input_array
|
|
92
|
+
"""
|
|
93
|
+
super().__init__(**kwargs)
|
|
94
|
+
self.number_of_dimensions = number_of_dimensions
|
|
95
|
+
|
|
96
|
+
def __array_finalize__(self, obj: Optional[np.ndarray]) -> None:
|
|
97
|
+
"""This method is called when the system allocates a new array from obj.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
obj: A subclass (subtype) of ndarray.
|
|
101
|
+
"""
|
|
102
|
+
if obj is None:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
self.units = getattr(obj, "units", None)
|
|
106
|
+
self.number_of_dimensions = getattr(obj, "number_of_dimensions", None) # type: ignore[assignment]
|
|
107
|
+
self.is_sparse = getattr(obj, "is_sparse", None)
|
|
108
|
+
|
|
109
|
+
default_attributes = {
|
|
110
|
+
"units": self.units,
|
|
111
|
+
"number_of_dimensions": self.number_of_dimensions,
|
|
112
|
+
"is_spare": self.is_sparse,
|
|
113
|
+
}
|
|
114
|
+
self.__dict__.update(default_attributes)
|
|
115
|
+
|
|
116
|
+
# pytype: disable=attribute-error
|
|
117
|
+
def __array_ufunc__(
|
|
118
|
+
self, ufunc: Any, method: Text, *inputs: Any, **kwargs: Any
|
|
119
|
+
) -> Any:
|
|
120
|
+
"""Overwrite this method as we are subclassing numpy array.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
ufunc: The ufunc object that was called.
|
|
124
|
+
method: A string indicating which Ufunc method was called
|
|
125
|
+
(one of "__call__", "reduce", "reduceat", "accumulate", "outer",
|
|
126
|
+
"inner").
|
|
127
|
+
*inputs: A tuple of the input arguments to the ufunc.
|
|
128
|
+
**kwargs: Any additional arguments
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
The result of the operation.
|
|
132
|
+
"""
|
|
133
|
+
f = {
|
|
134
|
+
"reduce": ufunc.reduce,
|
|
135
|
+
"accumulate": ufunc.accumulate,
|
|
136
|
+
"reduceat": ufunc.reduceat,
|
|
137
|
+
"outer": ufunc.outer,
|
|
138
|
+
"at": ufunc.at,
|
|
139
|
+
"__call__": ufunc,
|
|
140
|
+
}
|
|
141
|
+
# convert the inputs to np.ndarray to prevent recursion, call the function,
|
|
142
|
+
# then cast it back as FeatureArray
|
|
143
|
+
output = FeatureArray(
|
|
144
|
+
f[method](*(i.view(np.ndarray) for i in inputs), **kwargs),
|
|
145
|
+
number_of_dimensions=kwargs["number_of_dimensions"],
|
|
146
|
+
)
|
|
147
|
+
output.__dict__ = self.__dict__ # carry forward attributes
|
|
148
|
+
return output
|
|
149
|
+
|
|
150
|
+
def __reduce__(self) -> Tuple[Any, Any, Any]:
|
|
151
|
+
"""Needed in order to pickle this object.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
A tuple.
|
|
155
|
+
"""
|
|
156
|
+
pickled_state = super(FeatureArray, self).__reduce__()
|
|
157
|
+
if isinstance(pickled_state, str):
|
|
158
|
+
raise TypeError("np array __reduce__ returned string instead of tuple.")
|
|
159
|
+
new_state = pickled_state[2] + (
|
|
160
|
+
self.number_of_dimensions,
|
|
161
|
+
self.is_sparse,
|
|
162
|
+
self.units,
|
|
163
|
+
)
|
|
164
|
+
return pickled_state[0], pickled_state[1], new_state
|
|
165
|
+
|
|
166
|
+
def __setstate__(self, state: Any, **kwargs: Any) -> None:
|
|
167
|
+
"""Sets the state.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
state: The state argument must be a sequence that contains the following
|
|
171
|
+
elements version, shape, dtype, isFortan, rawdata.
|
|
172
|
+
**kwargs: Any additional parameter
|
|
173
|
+
"""
|
|
174
|
+
# Needed in order to load the object
|
|
175
|
+
self.number_of_dimensions = state[-3]
|
|
176
|
+
self.is_sparse = state[-2]
|
|
177
|
+
self.units = state[-1]
|
|
178
|
+
super(FeatureArray, self).__setstate__(state[0:-3], **kwargs)
|
|
179
|
+
|
|
180
|
+
# pytype: enable=attribute-error
|
|
181
|
+
|
|
182
|
+
@staticmethod
|
|
183
|
+
def _validate_number_of_dimensions(
|
|
184
|
+
number_of_dimensions: int, input_array: np.ndarray
|
|
185
|
+
) -> None:
|
|
186
|
+
"""Validates if the the input array has given number of dimensions.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
number_of_dimensions: number of dimensions
|
|
190
|
+
input_array: input array
|
|
191
|
+
|
|
192
|
+
Raises: ValueError in case the dimensions do not match
|
|
193
|
+
"""
|
|
194
|
+
_sub_array = input_array
|
|
195
|
+
dim = 0
|
|
196
|
+
# Go number_of_dimensions into the given input_array
|
|
197
|
+
for i in range(1, number_of_dimensions + 1):
|
|
198
|
+
_sub_array = _sub_array[0]
|
|
199
|
+
if isinstance(_sub_array, scipy.sparse.spmatrix):
|
|
200
|
+
dim = i
|
|
201
|
+
break
|
|
202
|
+
if isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
|
|
203
|
+
# sequence dimension is 0, we are dealing with "fake" features
|
|
204
|
+
dim = i
|
|
205
|
+
break
|
|
206
|
+
|
|
207
|
+
# If the resulting sub_array is sparse, the remaining number of dimensions
|
|
208
|
+
# should be at least 2
|
|
209
|
+
if isinstance(_sub_array, scipy.sparse.spmatrix):
|
|
210
|
+
if dim > 2:
|
|
211
|
+
raise ValueError(
|
|
212
|
+
f"Given number of dimensions '{number_of_dimensions}' does not "
|
|
213
|
+
f"match dimensions of given input array: {input_array}."
|
|
214
|
+
)
|
|
215
|
+
elif isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
|
|
216
|
+
# sequence dimension is 0, we are dealing with "fake" features,
|
|
217
|
+
# but they should be of dim 2
|
|
218
|
+
if dim > 2:
|
|
219
|
+
raise ValueError(
|
|
220
|
+
f"Given number of dimensions '{number_of_dimensions}' does not "
|
|
221
|
+
f"match dimensions of given input array: {input_array}."
|
|
222
|
+
)
|
|
223
|
+
# If the resulting sub_array is dense, the sub_array should be a single number
|
|
224
|
+
elif not np.issubdtype(type(_sub_array), np.integer) and not isinstance(
|
|
225
|
+
_sub_array, (np.float32, np.float64)
|
|
226
|
+
):
|
|
227
|
+
raise ValueError(
|
|
228
|
+
f"Given number of dimensions '{number_of_dimensions}' does not match "
|
|
229
|
+
f"dimensions of given input array: {input_array}."
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
42
233
|
class FeatureSignature(NamedTuple):
|
|
43
234
|
"""Signature of feature arrays.
|
|
44
235
|
|
rasa/validator.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
3
|
import string
|
|
4
|
-
import sys
|
|
5
4
|
from collections import defaultdict
|
|
6
5
|
from typing import Set, Text, Optional, Dict, Any, List, Tuple
|
|
7
6
|
|
|
@@ -23,11 +22,6 @@ from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
|
23
22
|
from rasa.shared.core.flows.steps.action import ActionFlowStep
|
|
24
23
|
from rasa.shared.core.flows.steps.link import LinkFlowStep
|
|
25
24
|
from rasa.shared.core.flows import FlowsList
|
|
26
|
-
from rasa.shared.core.flows.utils import (
|
|
27
|
-
warn_deprecated_collect_step_config,
|
|
28
|
-
get_duplicate_slot_persistence_config_error_message,
|
|
29
|
-
get_invalid_slot_persistence_config_error_message,
|
|
30
|
-
)
|
|
31
25
|
import rasa.shared.nlu.constants
|
|
32
26
|
from rasa.shared.constants import (
|
|
33
27
|
ASSISTANT_ID_DEFAULT_VALUE,
|
|
@@ -61,7 +55,6 @@ from rasa.shared.importers.importer import TrainingDataImporter
|
|
|
61
55
|
from rasa.shared.nlu.constants import COMMANDS
|
|
62
56
|
from rasa.shared.nlu.training_data.message import Message
|
|
63
57
|
from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
64
|
-
|
|
65
58
|
import rasa.shared.utils.cli
|
|
66
59
|
import rasa.shared.utils.io
|
|
67
60
|
|
|
@@ -305,7 +298,7 @@ class Validator:
|
|
|
305
298
|
return any(cls.check_for_placeholder(i) for i in value)
|
|
306
299
|
return False
|
|
307
300
|
|
|
308
|
-
def
|
|
301
|
+
def check_for_no_empty_paranthesis_in_responses(self) -> bool:
|
|
309
302
|
"""Checks if there are no empty parenthesis in utterances."""
|
|
310
303
|
everything_is_alright = True
|
|
311
304
|
|
|
@@ -316,12 +309,12 @@ class Validator:
|
|
|
316
309
|
for key in RESPONSE_KEYS_TO_INTERPOLATE
|
|
317
310
|
):
|
|
318
311
|
structlogger.error(
|
|
319
|
-
"validator.
|
|
312
|
+
"validator.empty_paranthesis_in_utterances",
|
|
320
313
|
response=response_text,
|
|
321
314
|
event_info=(
|
|
322
315
|
f"The response '{response_text}' in the domain file "
|
|
323
|
-
f"contains empty parenthesis, which is not permitted.
|
|
324
|
-
f"Please remove the empty parenthesis."
|
|
316
|
+
f"contains empty parenthesis, which is not permitted."
|
|
317
|
+
f" Please remove the empty parenthesis."
|
|
325
318
|
),
|
|
326
319
|
)
|
|
327
320
|
everything_is_alright = False
|
|
@@ -1244,7 +1237,6 @@ class Validator:
|
|
|
1244
1237
|
self.verify_flows_steps_against_domain(),
|
|
1245
1238
|
self.verify_unique_flows(),
|
|
1246
1239
|
self.verify_predicates(),
|
|
1247
|
-
self.verify_slot_persistence_configuration(),
|
|
1248
1240
|
]
|
|
1249
1241
|
|
|
1250
1242
|
all_good = all(flow_validation_conditions)
|
|
@@ -1541,101 +1533,3 @@ class Validator:
|
|
|
1541
1533
|
),
|
|
1542
1534
|
)
|
|
1543
1535
|
return False
|
|
1544
|
-
|
|
1545
|
-
def verify_slot_persistence_configuration(self) -> bool:
|
|
1546
|
-
"""Verifies the validity of slot persistence after flow ends configuration.
|
|
1547
|
-
|
|
1548
|
-
Only slots used in either a collect step or a set_slot step can be persisted and
|
|
1549
|
-
the configuration can either set at the flow level or the collect step level,
|
|
1550
|
-
but not both.
|
|
1551
|
-
|
|
1552
|
-
Returns:
|
|
1553
|
-
bool: True if all slot persistence configuration is valid, False otherwise.
|
|
1554
|
-
|
|
1555
|
-
Raises:
|
|
1556
|
-
DeprecationWarning: If reset_after_flow_ends is used in collect steps.
|
|
1557
|
-
"""
|
|
1558
|
-
all_good = True
|
|
1559
|
-
|
|
1560
|
-
for flow in self.flows.underlying_flows:
|
|
1561
|
-
flow_id = flow.id
|
|
1562
|
-
persist_slots = flow.persisted_slots
|
|
1563
|
-
has_flow_level_persistence = True if persist_slots else False
|
|
1564
|
-
flow_slots = set()
|
|
1565
|
-
|
|
1566
|
-
for step in flow.steps_with_calls_resolved:
|
|
1567
|
-
if isinstance(step, SetSlotsFlowStep):
|
|
1568
|
-
flow_slots.update([slot["key"] for slot in step.slots])
|
|
1569
|
-
|
|
1570
|
-
elif isinstance(step, CollectInformationFlowStep):
|
|
1571
|
-
collect_step = step.collect
|
|
1572
|
-
flow_slots.add(collect_step)
|
|
1573
|
-
if not step.reset_after_flow_ends:
|
|
1574
|
-
warn_deprecated_collect_step_config(flow_id, collect_step)
|
|
1575
|
-
|
|
1576
|
-
if has_flow_level_persistence:
|
|
1577
|
-
structlogger.error(
|
|
1578
|
-
"validator.verify_slot_persistence_configuration.duplicate_config",
|
|
1579
|
-
flow=flow_id,
|
|
1580
|
-
collect_step=collect_step,
|
|
1581
|
-
event_info=get_duplicate_slot_persistence_config_error_message(
|
|
1582
|
-
flow_id, collect_step
|
|
1583
|
-
),
|
|
1584
|
-
)
|
|
1585
|
-
all_good = False
|
|
1586
|
-
|
|
1587
|
-
if has_flow_level_persistence:
|
|
1588
|
-
if not self._is_persist_slots_valid(persist_slots, flow_slots, flow_id):
|
|
1589
|
-
all_good = False
|
|
1590
|
-
return all_good
|
|
1591
|
-
|
|
1592
|
-
def _is_persist_slots_valid(
|
|
1593
|
-
self, persist_slots: List[str], flow_slots: Set[str], flow_id: str
|
|
1594
|
-
) -> bool:
|
|
1595
|
-
invalid_slots = set(persist_slots) - flow_slots
|
|
1596
|
-
is_valid = False if invalid_slots else True
|
|
1597
|
-
|
|
1598
|
-
if invalid_slots:
|
|
1599
|
-
structlogger.error(
|
|
1600
|
-
"validator.verify_slot_persistence_configuration.invalid_persist_slot",
|
|
1601
|
-
flow=flow_id,
|
|
1602
|
-
event_info=get_invalid_slot_persistence_config_error_message(
|
|
1603
|
-
flow_id, invalid_slots
|
|
1604
|
-
),
|
|
1605
|
-
)
|
|
1606
|
-
return is_valid
|
|
1607
|
-
|
|
1608
|
-
def verify_studio_supported_validations(self) -> bool:
|
|
1609
|
-
"""Validates the assistant project for Rasa Studio supported features.
|
|
1610
|
-
|
|
1611
|
-
Ensure to add new validations here if they are required for
|
|
1612
|
-
Rasa Studio Upload CLI.
|
|
1613
|
-
"""
|
|
1614
|
-
if self.domain.is_empty():
|
|
1615
|
-
structlogger.error(
|
|
1616
|
-
"rasa.validator.verify_studio_supported_validations.empty_domain",
|
|
1617
|
-
event_info="Encountered empty domain during validation.",
|
|
1618
|
-
)
|
|
1619
|
-
sys.exit(1)
|
|
1620
|
-
|
|
1621
|
-
self.warn_if_config_mandatory_keys_are_not_set()
|
|
1622
|
-
|
|
1623
|
-
valid_responses = (
|
|
1624
|
-
self.check_for_no_empty_parenthesis_in_responses()
|
|
1625
|
-
and self.validate_button_payloads()
|
|
1626
|
-
)
|
|
1627
|
-
valid_nlu = self.verify_nlu()
|
|
1628
|
-
valid_flows = all(
|
|
1629
|
-
[
|
|
1630
|
-
self.verify_flows_steps_against_domain(),
|
|
1631
|
-
self.verify_unique_flows(),
|
|
1632
|
-
self.verify_predicates(),
|
|
1633
|
-
]
|
|
1634
|
-
)
|
|
1635
|
-
valid_calm_slot_mappings = self.validate_CALM_slot_mappings()
|
|
1636
|
-
|
|
1637
|
-
all_good = (
|
|
1638
|
-
valid_responses and valid_nlu and valid_flows and valid_calm_slot_mappings
|
|
1639
|
-
)
|
|
1640
|
-
|
|
1641
|
-
return all_good
|
rasa/version.py
CHANGED