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/shared/utils/yaml.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import datetime
|
|
2
|
-
import io
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
5
4
|
import re
|
|
@@ -9,13 +8,19 @@ from dataclasses import field
|
|
|
9
8
|
from functools import lru_cache
|
|
10
9
|
from io import StringIO
|
|
11
10
|
from pathlib import Path
|
|
12
|
-
from typing import
|
|
11
|
+
from typing import Dict, List, Optional, Any, Callable, Tuple, Union
|
|
13
12
|
|
|
14
13
|
import jsonschema
|
|
15
14
|
from importlib_resources import files
|
|
16
15
|
from packaging import version
|
|
17
16
|
from pykwalify.core import Core
|
|
18
17
|
from pykwalify.errors import SchemaError
|
|
18
|
+
from ruamel import yaml as yaml
|
|
19
|
+
from ruamel.yaml import RoundTripRepresenter, YAMLError
|
|
20
|
+
from ruamel.yaml.constructor import DuplicateKeyError, BaseConstructor, ScalarNode
|
|
21
|
+
from ruamel.yaml.comments import CommentedSeq, CommentedMap
|
|
22
|
+
from ruamel.yaml.loader import SafeLoader
|
|
23
|
+
|
|
19
24
|
from rasa.shared.constants import (
|
|
20
25
|
ASSERTIONS_SCHEMA_EXTENSIONS_FILE,
|
|
21
26
|
ASSERTIONS_SCHEMA_FILE,
|
|
@@ -26,7 +31,6 @@ from rasa.shared.constants import (
|
|
|
26
31
|
LATEST_TRAINING_DATA_FORMAT_VERSION,
|
|
27
32
|
SCHEMA_EXTENSIONS_FILE,
|
|
28
33
|
RESPONSES_SCHEMA_FILE,
|
|
29
|
-
SENSITIVE_DATA,
|
|
30
34
|
)
|
|
31
35
|
from rasa.shared.exceptions import (
|
|
32
36
|
YamlException,
|
|
@@ -46,11 +50,6 @@ from rasa.shared.utils.io import (
|
|
|
46
50
|
raise_warning,
|
|
47
51
|
read_json_file,
|
|
48
52
|
)
|
|
49
|
-
from ruamel import yaml as yaml
|
|
50
|
-
from ruamel.yaml import YAML, RoundTripRepresenter, YAMLError
|
|
51
|
-
from ruamel.yaml.comments import CommentedSeq, CommentedMap
|
|
52
|
-
from ruamel.yaml.constructor import DuplicateKeyError, BaseConstructor, ScalarNode
|
|
53
|
-
from ruamel.yaml.loader import SafeLoader
|
|
54
53
|
|
|
55
54
|
logger = logging.getLogger(__name__)
|
|
56
55
|
|
|
@@ -63,17 +62,8 @@ READ_YAML_FILE_CACHE_MAXSIZE = os.environ.get(
|
|
|
63
62
|
|
|
64
63
|
@dataclass
|
|
65
64
|
class PathWithError:
|
|
66
|
-
"""Represents a validation error at a specific location in the YAML content.
|
|
67
|
-
|
|
68
|
-
Attributes:
|
|
69
|
-
message (str): A description of the validation error.
|
|
70
|
-
path (List[str]): Path to the node where the error occurred.
|
|
71
|
-
key (Optional[str]): The specific key associated with the error, if any.
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
65
|
message: str
|
|
75
66
|
path: List[str] = field(default_factory=list)
|
|
76
|
-
key: Optional[str] = None
|
|
77
67
|
|
|
78
68
|
|
|
79
69
|
def fix_yaml_loader() -> None:
|
|
@@ -97,12 +87,6 @@ def replace_environment_variables() -> None:
|
|
|
97
87
|
def env_var_constructor(loader: BaseConstructor, node: ScalarNode) -> str:
|
|
98
88
|
"""Process environment variables found in the YAML."""
|
|
99
89
|
value = loader.construct_scalar(node)
|
|
100
|
-
|
|
101
|
-
# get key of current node
|
|
102
|
-
key_node = list(loader.constructed_objects)[-1]
|
|
103
|
-
if isinstance(key_node, ScalarNode) and key_node.value in SENSITIVE_DATA:
|
|
104
|
-
return value
|
|
105
|
-
|
|
106
90
|
expanded_vars = os.path.expandvars(value)
|
|
107
91
|
not_expanded = [
|
|
108
92
|
w for w in expanded_vars.split() if w.startswith("$") and w in value
|
|
@@ -120,6 +104,7 @@ def replace_environment_variables() -> None:
|
|
|
120
104
|
|
|
121
105
|
|
|
122
106
|
fix_yaml_loader()
|
|
107
|
+
replace_environment_variables()
|
|
123
108
|
|
|
124
109
|
|
|
125
110
|
class YamlValidationException(YamlException, ValueError):
|
|
@@ -153,72 +138,21 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
153
138
|
if self.validation_errors:
|
|
154
139
|
unique_errors = {}
|
|
155
140
|
for error in self.validation_errors:
|
|
156
|
-
line_number = self._line_number_for_path(
|
|
157
|
-
self.content, error.path, error.key
|
|
158
|
-
)
|
|
141
|
+
line_number = self._line_number_for_path(self.content, error.path)
|
|
159
142
|
|
|
160
143
|
if line_number and self.filename:
|
|
161
|
-
|
|
144
|
+
error_representation = f" in {self.filename}:{line_number}:\n"
|
|
162
145
|
elif line_number:
|
|
163
|
-
|
|
146
|
+
error_representation = f" in Line {line_number}:\n"
|
|
164
147
|
else:
|
|
165
|
-
|
|
148
|
+
error_representation = ""
|
|
166
149
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
unique_errors[error.message] = error_message
|
|
150
|
+
error_representation += f" {error.message}"
|
|
151
|
+
unique_errors[error.message] = error_representation
|
|
170
152
|
error_msg = "\n".join(unique_errors.values())
|
|
171
153
|
msg += f":\n{error_msg}"
|
|
172
154
|
return msg
|
|
173
155
|
|
|
174
|
-
def _get_code_snippet(
|
|
175
|
-
self,
|
|
176
|
-
error_line: Optional[int],
|
|
177
|
-
context_lines: int = 2,
|
|
178
|
-
) -> str:
|
|
179
|
-
"""Extract code snippet from the YAML lines around the error.
|
|
180
|
-
|
|
181
|
-
Args:
|
|
182
|
-
error_line: Line number where the error occurred (1-based).
|
|
183
|
-
context_lines: Number of context lines before and after the error line.
|
|
184
|
-
Default is 2, balancing context and readability. Adjust as needed.
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
A string containing the code snippet with the error highlighted.
|
|
188
|
-
"""
|
|
189
|
-
yaml_lines = self._get_serialized_yaml_lines()
|
|
190
|
-
if not yaml_lines or error_line is None:
|
|
191
|
-
return ""
|
|
192
|
-
|
|
193
|
-
start = max(error_line - context_lines - 1, 0)
|
|
194
|
-
end = min(error_line + context_lines, len(yaml_lines))
|
|
195
|
-
snippet_lines = yaml_lines[start:end]
|
|
196
|
-
snippet = ""
|
|
197
|
-
for idx, line_content in enumerate(snippet_lines, start=start + 1):
|
|
198
|
-
prefix = ">>> " if idx == error_line else " "
|
|
199
|
-
line_number_str = str(idx)
|
|
200
|
-
snippet += f"{prefix}{line_number_str} | {line_content}\n"
|
|
201
|
-
return snippet
|
|
202
|
-
|
|
203
|
-
def _get_serialized_yaml_lines(self) -> List[str]:
|
|
204
|
-
"""Serialize the content back to YAML and return the lines."""
|
|
205
|
-
yaml_lines = []
|
|
206
|
-
try:
|
|
207
|
-
yaml = YAML()
|
|
208
|
-
yaml.default_flow_style = False
|
|
209
|
-
# Set width to 1000, so we don't break the lines of the original YAML file
|
|
210
|
-
yaml.width = 1000 # type: ignore[assignment]
|
|
211
|
-
yaml.indent(mapping=2, sequence=4, offset=2)
|
|
212
|
-
stream = io.StringIO()
|
|
213
|
-
yaml.dump(self.content, stream)
|
|
214
|
-
serialized_yaml = stream.getvalue()
|
|
215
|
-
yaml_lines = serialized_yaml.splitlines()
|
|
216
|
-
return yaml_lines
|
|
217
|
-
except Exception as exc:
|
|
218
|
-
logger.debug(f"Error serializing YAML content: {exc}")
|
|
219
|
-
|
|
220
|
-
return yaml_lines
|
|
221
|
-
|
|
222
156
|
def _calculate_number_of_lines(
|
|
223
157
|
self,
|
|
224
158
|
current: Union[CommentedSeq, CommentedMap],
|
|
@@ -286,9 +220,7 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
286
220
|
# Return the calculated child offset and True indicating a line number was found
|
|
287
221
|
return child_offset, True
|
|
288
222
|
|
|
289
|
-
def _line_number_for_path(
|
|
290
|
-
self, current: Any, path: List[str], key: Optional[str] = None
|
|
291
|
-
) -> Optional[int]:
|
|
223
|
+
def _line_number_for_path(self, current: Any, path: List[str]) -> Optional[int]:
|
|
292
224
|
"""Get line number for a yaml path in the current content.
|
|
293
225
|
|
|
294
226
|
Implemented using recursion: algorithm goes down the path navigating to the
|
|
@@ -297,7 +229,6 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
297
229
|
Args:
|
|
298
230
|
current: current content
|
|
299
231
|
path: path to traverse within the content
|
|
300
|
-
key: the key associated with the error, if any
|
|
301
232
|
|
|
302
233
|
Returns:
|
|
303
234
|
the line number of the path in the content.
|
|
@@ -308,10 +239,6 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
308
239
|
this_line = current.lc.line + 1 if hasattr(current, "lc") else None
|
|
309
240
|
|
|
310
241
|
if not path:
|
|
311
|
-
if key and hasattr(current, "lc"):
|
|
312
|
-
if hasattr(current.lc, "data") and key in current.lc.data:
|
|
313
|
-
key_line_no = current.lc.data[key][0] + 1
|
|
314
|
-
return key_line_no
|
|
315
242
|
return this_line
|
|
316
243
|
|
|
317
244
|
head, tail = path[0], path[1:]
|
|
@@ -321,7 +248,7 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
321
248
|
|
|
322
249
|
if head:
|
|
323
250
|
if isinstance(current, dict) and head in current:
|
|
324
|
-
line = self._line_number_for_path(current[head], tail
|
|
251
|
+
line = self._line_number_for_path(current[head], tail)
|
|
325
252
|
if line is None:
|
|
326
253
|
line_offset, found_lc = self._calculate_number_of_lines(
|
|
327
254
|
current, head
|
|
@@ -331,17 +258,14 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
331
258
|
return this_line + line_offset
|
|
332
259
|
return line
|
|
333
260
|
elif isinstance(current, list) and head.isdigit():
|
|
334
|
-
return (
|
|
335
|
-
self._line_number_for_path(current[int(head)], tail, key)
|
|
336
|
-
or this_line
|
|
337
|
-
)
|
|
261
|
+
return self._line_number_for_path(current[int(head)], tail) or this_line
|
|
338
262
|
else:
|
|
339
263
|
return this_line
|
|
340
|
-
return self._line_number_for_path(current, tail
|
|
264
|
+
return self._line_number_for_path(current, tail) or this_line
|
|
341
265
|
|
|
342
266
|
|
|
343
267
|
def read_schema_file(
|
|
344
|
-
schema_file: str, package_name: str = PACKAGE_NAME
|
|
268
|
+
schema_file: str, package_name: str = PACKAGE_NAME
|
|
345
269
|
) -> Union[List[Any], Dict[str, Any]]:
|
|
346
270
|
"""Read a schema file from the package.
|
|
347
271
|
|
|
@@ -349,13 +273,12 @@ def read_schema_file(
|
|
|
349
273
|
schema_file: The schema file to read.
|
|
350
274
|
package_name: the name of the package the schema is located in. defaults
|
|
351
275
|
to `rasa`.
|
|
352
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
353
276
|
|
|
354
277
|
Returns:
|
|
355
278
|
The schema as a dictionary.
|
|
356
279
|
"""
|
|
357
280
|
schema_path = str(files(package_name).joinpath(schema_file))
|
|
358
|
-
return read_yaml_file(schema_path
|
|
281
|
+
return read_yaml_file(schema_path)
|
|
359
282
|
|
|
360
283
|
|
|
361
284
|
def parse_raw_yaml(raw_yaml_content: str) -> Dict[str, Any]:
|
|
@@ -400,26 +323,13 @@ def validate_yaml_content_using_schema(
|
|
|
400
323
|
try:
|
|
401
324
|
core.validate(raise_exception=True)
|
|
402
325
|
except SchemaError:
|
|
403
|
-
# PyKwalify propagates each validation error up the data hierarchy, resulting
|
|
404
|
-
# in multiple redundant errors for a single issue. To present a clear message
|
|
405
|
-
# about the root cause, we use only the first error.
|
|
406
|
-
error = core.errors[0]
|
|
407
|
-
|
|
408
|
-
# Increment numeric indices by 1 to convert from 0-based to 1-based indexing
|
|
409
|
-
error_message = re.sub(
|
|
410
|
-
r"(/)(\d+)", lambda m: f"/{int(m.group(2)) + 1}", str(error)
|
|
411
|
-
)
|
|
412
|
-
|
|
413
326
|
raise YamlValidationException(
|
|
414
327
|
"Please make sure the file is correct and all "
|
|
415
328
|
"mandatory parameters are specified. Here are the errors "
|
|
416
329
|
"found during validation",
|
|
417
330
|
[
|
|
418
|
-
PathWithError(
|
|
419
|
-
|
|
420
|
-
path=error.path.removeprefix("/").split("/"),
|
|
421
|
-
key=getattr(error, "key", None),
|
|
422
|
-
)
|
|
331
|
+
PathWithError(message=str(e), path=e.path.split("/"))
|
|
332
|
+
for e in core.errors
|
|
423
333
|
],
|
|
424
334
|
content=yaml_content,
|
|
425
335
|
)
|
|
@@ -429,7 +339,6 @@ def validate_raw_yaml_using_schema(
|
|
|
429
339
|
raw_yaml_content: str,
|
|
430
340
|
schema_content: Dict[str, Any],
|
|
431
341
|
schema_extensions: Optional[List[str]] = None,
|
|
432
|
-
expand_env_vars: bool = True,
|
|
433
342
|
) -> None:
|
|
434
343
|
"""Validate raw yaml content using a schema.
|
|
435
344
|
|
|
@@ -439,7 +348,6 @@ def validate_raw_yaml_using_schema(
|
|
|
439
348
|
raw_yaml_content: the raw YAML content to be validated (usually a string)
|
|
440
349
|
schema_content: the schema for the yaml_file_content
|
|
441
350
|
schema_extensions: pykwalify schema extension files
|
|
442
|
-
expand_env_vars: Whether to expand environment variables.
|
|
443
351
|
"""
|
|
444
352
|
try:
|
|
445
353
|
# we need "rt" since
|
|
@@ -447,11 +355,7 @@ def validate_raw_yaml_using_schema(
|
|
|
447
355
|
# will include e.g. at which line an object was parsed. this is very
|
|
448
356
|
# helpful when we validate files later on and want to point the user to the
|
|
449
357
|
# right line
|
|
450
|
-
yaml_data = read_yaml(
|
|
451
|
-
raw_yaml_content,
|
|
452
|
-
reader_type=["safe", "rt"],
|
|
453
|
-
expand_env_vars=expand_env_vars,
|
|
454
|
-
)
|
|
358
|
+
yaml_data = read_yaml(raw_yaml_content, reader_type=["safe", "rt"])
|
|
455
359
|
except (YAMLError, DuplicateKeyError) as e:
|
|
456
360
|
raise YamlSyntaxException(underlying_yaml_exception=e)
|
|
457
361
|
|
|
@@ -459,10 +363,7 @@ def validate_raw_yaml_using_schema(
|
|
|
459
363
|
|
|
460
364
|
|
|
461
365
|
def validate_raw_yaml_using_schema_file(
|
|
462
|
-
raw_yaml_content: str,
|
|
463
|
-
schema_path: str,
|
|
464
|
-
package_name: str = PACKAGE_NAME,
|
|
465
|
-
expand_env_vars: bool = True,
|
|
366
|
+
raw_yaml_content: str, schema_path: str, package_name: str = PACKAGE_NAME
|
|
466
367
|
) -> None:
|
|
467
368
|
"""Validate raw yaml content using a schema from file.
|
|
468
369
|
|
|
@@ -471,21 +372,15 @@ def validate_raw_yaml_using_schema_file(
|
|
|
471
372
|
schema_path: the schema used for validation
|
|
472
373
|
package_name: the name of the package the schema is located in. defaults
|
|
473
374
|
to `rasa`.
|
|
474
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
475
375
|
"""
|
|
476
|
-
schema_content = read_schema_file(
|
|
477
|
-
|
|
478
|
-
)
|
|
479
|
-
validate_raw_yaml_using_schema(
|
|
480
|
-
raw_yaml_content, schema_content, expand_env_vars=expand_env_vars
|
|
481
|
-
)
|
|
376
|
+
schema_content = read_schema_file(schema_path, package_name)
|
|
377
|
+
validate_raw_yaml_using_schema(raw_yaml_content, schema_content)
|
|
482
378
|
|
|
483
379
|
|
|
484
380
|
def validate_raw_yaml_content_using_schema_with_responses(
|
|
485
381
|
raw_yaml_content: str,
|
|
486
382
|
schema_content: Union[List[Any], Dict[str, Any]],
|
|
487
383
|
package_name: str = PACKAGE_NAME,
|
|
488
|
-
expand_env_vars: bool = True,
|
|
489
384
|
) -> None:
|
|
490
385
|
"""Validate raw yaml content using a schema with responses sub-schema.
|
|
491
386
|
|
|
@@ -494,26 +389,18 @@ def validate_raw_yaml_content_using_schema_with_responses(
|
|
|
494
389
|
schema_content: the content of the YAML schema
|
|
495
390
|
package_name: the name of the package the schema is located in. defaults
|
|
496
391
|
to `rasa`.
|
|
497
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
498
392
|
"""
|
|
499
393
|
# bot responses are part of the schema extension
|
|
500
394
|
# it will be included if the schema explicitly references it with include: responses
|
|
501
|
-
bot_responses_schema_content = read_schema_file(
|
|
502
|
-
RESPONSES_SCHEMA_FILE, package_name, expand_env_vars=expand_env_vars
|
|
503
|
-
)
|
|
395
|
+
bot_responses_schema_content = read_schema_file(RESPONSES_SCHEMA_FILE, package_name)
|
|
504
396
|
schema_content = dict(schema_content, **bot_responses_schema_content)
|
|
505
397
|
schema_extensions = [str(files(package_name).joinpath(SCHEMA_EXTENSIONS_FILE))]
|
|
506
398
|
|
|
507
|
-
validate_raw_yaml_using_schema(
|
|
508
|
-
raw_yaml_content, schema_content, schema_extensions, expand_env_vars
|
|
509
|
-
)
|
|
399
|
+
validate_raw_yaml_using_schema(raw_yaml_content, schema_content, schema_extensions)
|
|
510
400
|
|
|
511
401
|
|
|
512
402
|
def validate_raw_yaml_using_schema_file_with_responses(
|
|
513
|
-
raw_yaml_content: str,
|
|
514
|
-
schema_path: str,
|
|
515
|
-
package_name: str = PACKAGE_NAME,
|
|
516
|
-
expand_env_vars: bool = True,
|
|
403
|
+
raw_yaml_content: str, schema_path: str, package_name: str = PACKAGE_NAME
|
|
517
404
|
) -> None:
|
|
518
405
|
"""Validate domain yaml content using a schema from file with responses sub-schema.
|
|
519
406
|
|
|
@@ -522,12 +409,52 @@ def validate_raw_yaml_using_schema_file_with_responses(
|
|
|
522
409
|
schema_path: the schema of the yaml file
|
|
523
410
|
package_name: the name of the package the schema is located in. defaults
|
|
524
411
|
to `rasa`.
|
|
525
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
526
412
|
"""
|
|
527
|
-
schema_content = read_schema_file(schema_path, package_name
|
|
413
|
+
schema_content = read_schema_file(schema_path, package_name)
|
|
528
414
|
validate_raw_yaml_content_using_schema_with_responses(
|
|
529
|
-
raw_yaml_content, schema_content, package_name
|
|
415
|
+
raw_yaml_content, schema_content, package_name
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def process_content(content: str) -> str:
|
|
420
|
+
"""
|
|
421
|
+
Process the content to handle both Windows paths and emojis.
|
|
422
|
+
Windows paths are processed by escaping backslashes but emojis are left untouched.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
content: yaml content to be processed
|
|
426
|
+
"""
|
|
427
|
+
# Detect common Windows path patterns: e.g., C:\ or \\
|
|
428
|
+
UNESCAPED_WINDOWS_PATH_PATTERN = re.compile(
|
|
429
|
+
r"(?<!\w)[a-zA-Z]:(\\[a-zA-Z0-9_ -]+)*(\\)?(?!\\n)"
|
|
530
430
|
)
|
|
431
|
+
ESCAPED_WINDOWS_PATH_PATTERN = re.compile(
|
|
432
|
+
r"(?<!\w)[a-zA-Z]:(\\\\[a-zA-Z0-9_ -]+)+\\\\?(?!\\n)"
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
# Function to escape backslashes in Windows paths but leave other content as is
|
|
436
|
+
def escape_windows_paths(match: re.Match) -> str:
|
|
437
|
+
path = str(match.group(0))
|
|
438
|
+
return path.replace("\\", "\\\\") # Escape backslashes only in Windows paths
|
|
439
|
+
|
|
440
|
+
def unescape_windows_paths(match: re.Match) -> str:
|
|
441
|
+
path = str(match.group(0))
|
|
442
|
+
return path.replace("\\\\", "\\")
|
|
443
|
+
|
|
444
|
+
# First, process Windows paths by escaping backslashes
|
|
445
|
+
content = re.sub(UNESCAPED_WINDOWS_PATH_PATTERN, escape_windows_paths, content)
|
|
446
|
+
|
|
447
|
+
# Ensure proper handling of emojis by decoding Unicode sequences
|
|
448
|
+
content = (
|
|
449
|
+
content.encode("utf-8")
|
|
450
|
+
.decode("raw_unicode_escape")
|
|
451
|
+
.encode("utf-16", "surrogatepass")
|
|
452
|
+
.decode("utf-16")
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
content = re.sub(ESCAPED_WINDOWS_PATH_PATTERN, unescape_windows_paths, content)
|
|
456
|
+
|
|
457
|
+
return content
|
|
531
458
|
|
|
532
459
|
|
|
533
460
|
def read_yaml(
|
|
@@ -545,15 +472,15 @@ def read_yaml(
|
|
|
545
472
|
Raises:
|
|
546
473
|
ruamel.yaml.parser.ParserError: If there was an error when parsing the YAML.
|
|
547
474
|
"""
|
|
475
|
+
if _is_ascii(content):
|
|
476
|
+
content = process_content(content)
|
|
477
|
+
|
|
548
478
|
custom_constructor = kwargs.get("custom_constructor", None)
|
|
549
|
-
expand_env_vars = kwargs.get("expand_env_vars", True)
|
|
550
479
|
|
|
551
480
|
# Create YAML parser with custom constructor
|
|
552
481
|
yaml_parser, reset_constructors = create_yaml_parser(
|
|
553
482
|
reader_type, custom_constructor
|
|
554
483
|
)
|
|
555
|
-
if expand_env_vars:
|
|
556
|
-
replace_environment_variables()
|
|
557
484
|
yaml_content = yaml_parser.load(content) or {}
|
|
558
485
|
|
|
559
486
|
# Reset to default constructors
|
|
@@ -609,10 +536,6 @@ def create_yaml_parser(
|
|
|
609
536
|
yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG,
|
|
610
537
|
original_sequence_constructor,
|
|
611
538
|
)
|
|
612
|
-
# replace env var constructor with one that does not expand env vars
|
|
613
|
-
yaml_parser.constructor.add_constructor(
|
|
614
|
-
"!env_var", lambda loader, node: loader.construct_scalar(node)
|
|
615
|
-
)
|
|
616
539
|
|
|
617
540
|
def custom_date_constructor(loader: SafeLoader, node: ScalarNode) -> str:
|
|
618
541
|
"""Custom constructor for parsing dates in the format '%Y-%m-%d'.
|
|
@@ -647,9 +570,7 @@ def _is_ascii(text: str) -> bool:
|
|
|
647
570
|
|
|
648
571
|
@lru_cache(maxsize=READ_YAML_FILE_CACHE_MAXSIZE)
|
|
649
572
|
def read_yaml_file(
|
|
650
|
-
filename: Union[str, Path],
|
|
651
|
-
reader_type: Union[str, Tuple[str]] = "safe",
|
|
652
|
-
expand_env_vars: bool = True,
|
|
573
|
+
filename: Union[str, Path], reader_type: Union[str, Tuple[str]] = "safe"
|
|
653
574
|
) -> Union[List[Any], Dict[str, Any]]:
|
|
654
575
|
"""Parses a yaml file.
|
|
655
576
|
|
|
@@ -658,7 +579,6 @@ def read_yaml_file(
|
|
|
658
579
|
Args:
|
|
659
580
|
filename: The path to the file which should be read.
|
|
660
581
|
reader_type: Reader type to use. By default "safe" will be used.
|
|
661
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
662
582
|
|
|
663
583
|
Returns:
|
|
664
584
|
Parsed content of the file.
|
|
@@ -667,11 +587,7 @@ def read_yaml_file(
|
|
|
667
587
|
fixed_reader_type = (
|
|
668
588
|
list(reader_type) if isinstance(reader_type, tuple) else reader_type
|
|
669
589
|
)
|
|
670
|
-
return read_yaml(
|
|
671
|
-
read_file(filename, DEFAULT_ENCODING),
|
|
672
|
-
fixed_reader_type,
|
|
673
|
-
expand_env_vars=expand_env_vars,
|
|
674
|
-
)
|
|
590
|
+
return read_yaml(read_file(filename, DEFAULT_ENCODING), fixed_reader_type)
|
|
675
591
|
except (YAMLError, DuplicateKeyError) as e:
|
|
676
592
|
raise YamlSyntaxException(filename, e)
|
|
677
593
|
|
|
@@ -694,14 +610,11 @@ def read_config_file(
|
|
|
694
610
|
return read_validated_yaml(filename, CONFIG_SCHEMA_FILE, reader_type)
|
|
695
611
|
|
|
696
612
|
|
|
697
|
-
def read_model_configuration(
|
|
698
|
-
filename: Union[Path, str], expand_env_vars: bool = True
|
|
699
|
-
) -> Dict[str, Any]:
|
|
613
|
+
def read_model_configuration(filename: Union[Path, str]) -> Dict[str, Any]:
|
|
700
614
|
"""Parses a model configuration file.
|
|
701
615
|
|
|
702
616
|
Args:
|
|
703
617
|
filename: The path to the file which should be read.
|
|
704
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
705
618
|
|
|
706
619
|
Raises:
|
|
707
620
|
YamlValidationException: In case the model configuration doesn't match the
|
|
@@ -710,9 +623,7 @@ def read_model_configuration(
|
|
|
710
623
|
Returns:
|
|
711
624
|
Parsed config file.
|
|
712
625
|
"""
|
|
713
|
-
return read_validated_yaml(
|
|
714
|
-
filename, MODEL_CONFIG_SCHEMA_FILE, expand_env_vars=expand_env_vars
|
|
715
|
-
)
|
|
626
|
+
return read_validated_yaml(filename, MODEL_CONFIG_SCHEMA_FILE)
|
|
716
627
|
|
|
717
628
|
|
|
718
629
|
def dump_obj_as_yaml_to_string(
|
|
@@ -810,7 +721,6 @@ def read_validated_yaml(
|
|
|
810
721
|
filename: Union[str, Path],
|
|
811
722
|
schema: str,
|
|
812
723
|
reader_type: Union[str, List[str]] = "safe",
|
|
813
|
-
expand_env_vars: bool = True,
|
|
814
724
|
) -> Any:
|
|
815
725
|
"""Validates YAML file content and returns parsed content.
|
|
816
726
|
|
|
@@ -819,7 +729,6 @@ def read_validated_yaml(
|
|
|
819
729
|
schema: The path to the schema file which should be used for validating the
|
|
820
730
|
file content.
|
|
821
731
|
reader_type: Reader type to use. By default, "safe" will be used.
|
|
822
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
823
732
|
|
|
824
733
|
Returns:
|
|
825
734
|
The parsed file content.
|
|
@@ -830,10 +739,8 @@ def read_validated_yaml(
|
|
|
830
739
|
"""
|
|
831
740
|
content = read_file(filename)
|
|
832
741
|
|
|
833
|
-
validate_raw_yaml_using_schema_file(
|
|
834
|
-
|
|
835
|
-
)
|
|
836
|
-
return read_yaml(content, reader_type, expand_env_vars=expand_env_vars)
|
|
742
|
+
validate_raw_yaml_using_schema_file(content, schema)
|
|
743
|
+
return read_yaml(content, reader_type)
|
|
837
744
|
|
|
838
745
|
|
|
839
746
|
def validate_training_data(json_data: Dict[str, Any], schema: Dict[str, Any]) -> None:
|
|
@@ -952,7 +859,6 @@ def validate_yaml_with_jsonschema(
|
|
|
952
859
|
humanize_error: Callable[
|
|
953
860
|
[jsonschema.ValidationError], str
|
|
954
861
|
] = default_error_humanizer,
|
|
955
|
-
expand_env_vars: bool = True,
|
|
956
862
|
) -> None:
|
|
957
863
|
"""Validate data format.
|
|
958
864
|
|
|
@@ -963,7 +869,6 @@ def validate_yaml_with_jsonschema(
|
|
|
963
869
|
to `rasa`.
|
|
964
870
|
humanize_error: a function to convert a jsonschema.ValidationError into a
|
|
965
871
|
human-readable error message. Defaults to `default_error_humanizer`.
|
|
966
|
-
expand_env_vars: Whether to expand environment variables in the file.
|
|
967
872
|
|
|
968
873
|
Raises:
|
|
969
874
|
YamlSyntaxException: if the yaml file is not valid.
|
|
@@ -981,11 +886,7 @@ def validate_yaml_with_jsonschema(
|
|
|
981
886
|
# will include e.g. at which line an object was parsed. this is very
|
|
982
887
|
# helpful when we validate files later on and want to point the user to the
|
|
983
888
|
# right line
|
|
984
|
-
source_data = read_yaml(
|
|
985
|
-
yaml_file_content,
|
|
986
|
-
reader_type=["safe", "rt"],
|
|
987
|
-
expand_env_vars=expand_env_vars,
|
|
988
|
-
)
|
|
889
|
+
source_data = read_yaml(yaml_file_content, reader_type=["safe", "rt"])
|
|
989
890
|
except (YAMLError, DuplicateKeyError) as e:
|
|
990
891
|
raise YamlSyntaxException(underlying_yaml_exception=e)
|
|
991
892
|
|
rasa/studio/auth.py
CHANGED
|
@@ -23,10 +23,12 @@ from rasa.studio.results_logger import with_studio_error_handler, StudioResult
|
|
|
23
23
|
class StudioAuth:
|
|
24
24
|
"""Handles the authentication with the Rasa Studio authentication server."""
|
|
25
25
|
|
|
26
|
-
def __init__(
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
studio_config: StudioConfig,
|
|
29
|
+
verify: bool = True,
|
|
30
|
+
) -> None:
|
|
27
31
|
self.config = studio_config
|
|
28
|
-
verify = not studio_config.disable_verify
|
|
29
|
-
|
|
30
32
|
self.keycloak_openid = KeycloakOpenID(
|
|
31
33
|
server_url=studio_config.authentication_server_url,
|
|
32
34
|
client_id=studio_config.client_id,
|
rasa/studio/config.py
CHANGED
|
@@ -2,14 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Dict, Optional, Text
|
|
6
6
|
|
|
7
7
|
from rasa.utils.common import read_global_config_value, write_global_config_value
|
|
8
8
|
|
|
9
9
|
from rasa.studio.constants import (
|
|
10
10
|
RASA_STUDIO_AUTH_SERVER_URL_ENV,
|
|
11
11
|
RASA_STUDIO_CLI_CLIENT_ID_KEY_ENV,
|
|
12
|
-
RASA_STUDIO_CLI_DISABLE_VERIFY_KEY_ENV,
|
|
13
12
|
RASA_STUDIO_CLI_REALM_NAME_KEY_ENV,
|
|
14
13
|
RASA_STUDIO_CLI_STUDIO_URL_ENV,
|
|
15
14
|
STUDIO_CONFIG_KEY,
|
|
@@ -20,7 +19,6 @@ STUDIO_URL_KEY = "studio_url"
|
|
|
20
19
|
CLIENT_ID_KEY = "client_id"
|
|
21
20
|
REALM_NAME_KEY = "realm_name"
|
|
22
21
|
CLIENT_SECRET_KEY = "client_secret"
|
|
23
|
-
DISABLE_VERIFY = "disable_verify"
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
@dataclass
|
|
@@ -29,15 +27,13 @@ class StudioConfig:
|
|
|
29
27
|
studio_url: Optional[Text]
|
|
30
28
|
client_id: Optional[Text]
|
|
31
29
|
realm_name: Optional[Text]
|
|
32
|
-
disable_verify: bool = False
|
|
33
30
|
|
|
34
|
-
def to_dict(self) -> Dict[Text, Optional[
|
|
31
|
+
def to_dict(self) -> Dict[Text, Optional[Text]]:
|
|
35
32
|
return {
|
|
36
33
|
AUTH_SERVER_URL_KEY: self.authentication_server_url,
|
|
37
34
|
STUDIO_URL_KEY: self.studio_url,
|
|
38
35
|
CLIENT_ID_KEY: self.client_id,
|
|
39
36
|
REALM_NAME_KEY: self.realm_name,
|
|
40
|
-
DISABLE_VERIFY: self.disable_verify,
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
@classmethod
|
|
@@ -47,7 +43,6 @@ class StudioConfig:
|
|
|
47
43
|
studio_url=data[STUDIO_URL_KEY],
|
|
48
44
|
client_id=data[CLIENT_ID_KEY],
|
|
49
45
|
realm_name=data[REALM_NAME_KEY],
|
|
50
|
-
disable_verify=data.get(DISABLE_VERIFY, False),
|
|
51
46
|
)
|
|
52
47
|
|
|
53
48
|
def write_config(self) -> None:
|
|
@@ -78,7 +73,7 @@ class StudioConfig:
|
|
|
78
73
|
config = read_global_config_value(STUDIO_CONFIG_KEY, unavailable_ok=True)
|
|
79
74
|
|
|
80
75
|
if config is None:
|
|
81
|
-
return StudioConfig(None, None, None, None
|
|
76
|
+
return StudioConfig(None, None, None, None)
|
|
82
77
|
|
|
83
78
|
if not isinstance(config, dict):
|
|
84
79
|
raise ValueError(
|
|
@@ -88,7 +83,7 @@ class StudioConfig:
|
|
|
88
83
|
)
|
|
89
84
|
|
|
90
85
|
for key in config:
|
|
91
|
-
if not isinstance(config[key], str)
|
|
86
|
+
if not isinstance(config[key], str):
|
|
92
87
|
raise ValueError(
|
|
93
88
|
"Invalid config file format. "
|
|
94
89
|
f"Key '{key}' is not a text value."
|
|
@@ -107,9 +102,6 @@ class StudioConfig:
|
|
|
107
102
|
studio_url=StudioConfig._read_env_value(RASA_STUDIO_CLI_STUDIO_URL_ENV),
|
|
108
103
|
client_id=StudioConfig._read_env_value(RASA_STUDIO_CLI_CLIENT_ID_KEY_ENV),
|
|
109
104
|
realm_name=StudioConfig._read_env_value(RASA_STUDIO_CLI_REALM_NAME_KEY_ENV),
|
|
110
|
-
disable_verify=bool(
|
|
111
|
-
os.getenv(RASA_STUDIO_CLI_DISABLE_VERIFY_KEY_ENV, False)
|
|
112
|
-
),
|
|
113
105
|
)
|
|
114
106
|
|
|
115
107
|
@staticmethod
|
|
@@ -132,5 +124,4 @@ class StudioConfig:
|
|
|
132
124
|
studio_url=self.studio_url or other.studio_url,
|
|
133
125
|
client_id=self.client_id or other.client_id,
|
|
134
126
|
realm_name=self.realm_name or other.realm_name,
|
|
135
|
-
disable_verify=self.disable_verify or other.disable_verify,
|
|
136
127
|
)
|
rasa/studio/constants.py
CHANGED
|
@@ -10,7 +10,6 @@ RASA_STUDIO_AUTH_SERVER_URL_ENV = "RASA_STUDIO_AUTH_SERVER_URL"
|
|
|
10
10
|
RASA_STUDIO_CLI_STUDIO_URL_ENV = "RASA_STUDIO_CLI_STUDIO_URL"
|
|
11
11
|
RASA_STUDIO_CLI_REALM_NAME_KEY_ENV = "RASA_STUDIO_CLI_REALM_NAME_KEY"
|
|
12
12
|
RASA_STUDIO_CLI_CLIENT_ID_KEY_ENV = "RASA_STUDIO_CLI_CLIENT_ID_KEY"
|
|
13
|
-
RASA_STUDIO_CLI_DISABLE_VERIFY_KEY_ENV = "RASA_STUDIO_CLI_DISABLE_VERIFY_KEY"
|
|
14
13
|
|
|
15
14
|
STUDIO_NLU_FILENAME = "studio_nlu.yml"
|
|
16
15
|
STUDIO_DOMAIN_FILENAME = "studio_domain.yml"
|