rasa-pro 3.11.0a4.dev3__py3-none-any.whl → 3.11.0rc2__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.
- rasa/__main__.py +22 -12
- rasa/api.py +1 -1
- rasa/cli/arguments/default_arguments.py +1 -2
- rasa/cli/arguments/shell.py +5 -1
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +8 -8
- rasa/cli/inspect.py +6 -4
- rasa/cli/llm_fine_tuning.py +1 -1
- rasa/cli/project_templates/calm/config.yml +5 -7
- rasa/cli/project_templates/calm/endpoints.yml +8 -0
- rasa/cli/project_templates/tutorial/config.yml +8 -5
- rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +5 -0
- rasa/cli/project_templates/tutorial/domain.yml +14 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +7 -7
- rasa/cli/run.py +1 -1
- rasa/cli/scaffold.py +4 -2
- rasa/cli/studio/studio.py +18 -8
- rasa/cli/utils.py +5 -0
- rasa/cli/x.py +8 -8
- rasa/constants.py +1 -1
- rasa/core/actions/action_repeat_bot_messages.py +17 -0
- rasa/core/channels/channel.py +20 -0
- rasa/core/channels/inspector/dist/assets/{arc-6852c607.js → arc-bc141fb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-acc952b2.js → c4Diagram-d0fbc5ce-be2db283.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-848a7597.js → classDiagram-936ed81e-55366915.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-a73d3e68.js → classDiagram-v2-c3cb15f1-bb529518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-e5ee049d.js → createText-62fc7601-b0ec81d6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-771e517e.js → edges-f2ad444c-6166330c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-aa347178.js → erDiagram-9d236eb7-5ccc6a8e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-651fc57d.js → flowDb-1972c806-fca3bfe4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-ca67804f.js → flowDiagram-7ea5b25a-4739080f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-2dbc568d.js → flowchart-elk-definition-abe16c3d-7c1b0e0f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-25a65bd8.js → ganttDiagram-9b5ea136-772fd050.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-fdc7378d.js → gitGraphDiagram-99d0ae7c-8eae1dc9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-6f1fd606.js → index-2c4b9a3b-f55afcdf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-efdd30c1.js → index-e7cef9de.js} +68 -68
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-cb1a041a.js → infoDiagram-736b4530-124d4a14.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-14609879.js → journeyDiagram-df861f2b-7c4fae44.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-2490f52b.js → layout-b9885fb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-40186f1f.js → line-7c59abb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-08814e93.js → linear-4776f780.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-1a534584.js → mindmap-definition-beec6740-2332c46c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-72397b61.js → pieDiagram-dbbf0591-8fb39303.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-3bb0b6a3.js → quadrantDiagram-4d7f4fd6-3c7180a2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-57334f61.js → requirementDiagram-6fc4c22a-e910bcb8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-111e1297.js → sankeyDiagram-8f13d901-ead16c89.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-10bcfe62.js → sequenceDiagram-b655622a-29a02a19.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-acaf7513.js → stateDiagram-59f0c015-042b3137.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-3ec2a235.js → stateDiagram-v2-2b26beab-2178c0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-62730289.js → styles-080da4f6-23ffa4fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-5284ee76.js → styles-3dcbcfbf-94f59763.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-642435e3.js → styles-9c745c82-78a6bebc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-b250a350.js → svgDrawCommon-4835440b-eae2a6f6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-c2b147ed.js → timeline-definition-5b62e21b-5c968d92.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-f92cfea9.js → xychartDiagram-2b33534f-fd3db0d5.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 +77 -16
- rasa/core/channels/socketio.py +2 -1
- rasa/core/channels/telegram.py +1 -1
- rasa/core/channels/twilio.py +1 -1
- rasa/core/channels/voice_ready/audiocodes.py +12 -0
- rasa/core/channels/voice_ready/jambonz.py +15 -4
- rasa/core/channels/voice_ready/twilio_voice.py +6 -21
- rasa/core/channels/voice_stream/asr/asr_event.py +5 -0
- rasa/core/channels/voice_stream/asr/azure.py +122 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +16 -6
- rasa/core/channels/voice_stream/audio_bytes.py +1 -0
- rasa/core/channels/voice_stream/browser_audio.py +31 -8
- rasa/core/channels/voice_stream/call_state.py +23 -0
- rasa/core/channels/voice_stream/tts/azure.py +6 -2
- rasa/core/channels/voice_stream/tts/cartesia.py +10 -6
- rasa/core/channels/voice_stream/tts/tts_engine.py +1 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +27 -18
- rasa/core/channels/voice_stream/util.py +4 -4
- rasa/core/channels/voice_stream/voice_channel.py +189 -39
- rasa/core/featurizers/single_state_featurizer.py +22 -1
- rasa/core/featurizers/tracker_featurizers.py +115 -18
- rasa/core/nlg/contextual_response_rephraser.py +32 -30
- rasa/core/persistor.py +86 -39
- rasa/core/policies/enterprise_search_policy.py +119 -60
- rasa/core/policies/flows/flow_executor.py +7 -4
- rasa/core/policies/intentless_policy.py +78 -22
- rasa/core/policies/ted_policy.py +58 -33
- rasa/core/policies/unexpected_intent_policy.py +15 -7
- rasa/core/processor.py +25 -0
- rasa/core/training/interactive.py +34 -35
- rasa/core/utils.py +8 -3
- rasa/dialogue_understanding/coexistence/llm_based_router.py +39 -12
- rasa/dialogue_understanding/commands/change_flow_command.py +6 -0
- rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +5 -0
- rasa/dialogue_understanding/generator/constants.py +2 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +49 -4
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +37 -23
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +57 -10
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +19 -1
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +71 -11
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +39 -0
- rasa/dialogue_understanding/patterns/user_silence.py +37 -0
- rasa/dialogue_understanding/processor/command_processor.py +21 -1
- rasa/e2e_test/e2e_test_case.py +85 -6
- rasa/e2e_test/e2e_test_runner.py +4 -2
- rasa/e2e_test/utils/io.py +1 -1
- rasa/engine/validation.py +316 -10
- rasa/model_manager/config.py +15 -3
- rasa/model_manager/model_api.py +15 -7
- rasa/model_manager/runner_service.py +8 -6
- rasa/model_manager/socket_bridge.py +6 -3
- rasa/model_manager/trainer_service.py +7 -5
- rasa/model_manager/utils.py +28 -7
- rasa/model_service.py +9 -2
- rasa/model_training.py +2 -0
- rasa/nlu/classifiers/diet_classifier.py +38 -25
- rasa/nlu/classifiers/logistic_regression_classifier.py +22 -9
- rasa/nlu/classifiers/sklearn_intent_classifier.py +37 -16
- rasa/nlu/extractors/crf_entity_extractor.py +93 -50
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +45 -16
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +52 -17
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +5 -3
- rasa/nlu/tokenizers/whitespace_tokenizer.py +3 -14
- rasa/server.py +3 -1
- rasa/shared/constants.py +36 -3
- rasa/shared/core/constants.py +7 -0
- rasa/shared/core/domain.py +26 -0
- rasa/shared/core/flows/flow.py +5 -0
- rasa/shared/core/flows/flows_list.py +5 -1
- rasa/shared/core/flows/flows_yaml_schema.json +10 -0
- rasa/shared/core/flows/utils.py +39 -0
- rasa/shared/core/flows/validation.py +96 -0
- rasa/shared/core/slots.py +5 -0
- rasa/shared/nlu/training_data/features.py +120 -2
- rasa/shared/providers/_configs/azure_openai_client_config.py +5 -3
- rasa/shared/providers/_configs/litellm_router_client_config.py +200 -0
- rasa/shared/providers/_configs/model_group_config.py +167 -0
- rasa/shared/providers/_configs/openai_client_config.py +1 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +73 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -0
- rasa/shared/providers/_configs/utils.py +16 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +18 -29
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +54 -21
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +135 -0
- rasa/shared/providers/llm/_base_litellm_client.py +37 -31
- rasa/shared/providers/llm/azure_openai_llm_client.py +50 -29
- rasa/shared/providers/llm/litellm_router_llm_client.py +127 -0
- rasa/shared/providers/llm/rasa_llm_client.py +112 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +1 -1
- rasa/shared/providers/mappings.py +19 -0
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +149 -0
- rasa/shared/providers/router/router_client.py +73 -0
- rasa/shared/utils/common.py +8 -0
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
- rasa/shared/utils/health_check/health_check.py +256 -0
- rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
- rasa/shared/utils/io.py +28 -6
- rasa/shared/utils/llm.py +353 -46
- rasa/shared/utils/yaml.py +111 -73
- rasa/studio/auth.py +3 -5
- rasa/studio/config.py +13 -4
- rasa/studio/constants.py +1 -0
- rasa/studio/data_handler.py +10 -3
- rasa/studio/upload.py +81 -26
- rasa/telemetry.py +92 -17
- rasa/tracing/config.py +2 -0
- rasa/tracing/instrumentation/attribute_extractors.py +94 -17
- rasa/tracing/instrumentation/instrumentation.py +121 -0
- rasa/utils/common.py +5 -0
- rasa/utils/io.py +7 -81
- rasa/utils/log_utils.py +9 -2
- rasa/utils/sanic_error_handler.py +32 -0
- rasa/utils/tensorflow/feature_array.py +366 -0
- rasa/utils/tensorflow/model_data.py +2 -193
- rasa/validator.py +70 -0
- rasa/version.py +1 -1
- {rasa_pro-3.11.0a4.dev3.dist-info → rasa_pro-3.11.0rc2.dist-info}/METADATA +11 -10
- {rasa_pro-3.11.0a4.dev3.dist-info → rasa_pro-3.11.0rc2.dist-info}/RECORD +183 -163
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-587d82d8.js +0 -1
- {rasa_pro-3.11.0a4.dev3.dist-info → rasa_pro-3.11.0rc2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.11.0a4.dev3.dist-info → rasa_pro-3.11.0rc2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.11.0a4.dev3.dist-info → rasa_pro-3.11.0rc2.dist-info}/entry_points.txt +0 -0
rasa/shared/constants.py
CHANGED
|
@@ -183,7 +183,34 @@ STREAM_CONFIG_KEY = "stream"
|
|
|
183
183
|
N_REPHRASES_CONFIG_KEY = "n"
|
|
184
184
|
USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY = "use_chat_completions_endpoint"
|
|
185
185
|
|
|
186
|
+
ROUTER_CONFIG_KEY = "router"
|
|
187
|
+
ROUTER_STRATEGY_CONFIG_KEY = "router_strategy"
|
|
188
|
+
REDIS_HOST_CONFIG_KEY = "redis_host"
|
|
189
|
+
ROUTER_STRATEGIES_REQUIRING_REDIS_CACHE = [
|
|
190
|
+
"cost-based-routing",
|
|
191
|
+
"usage-based-routing",
|
|
192
|
+
]
|
|
193
|
+
ROUTER_STRATEGIES_NOT_REQUIRING_CACHE = [
|
|
194
|
+
"latency-based-routing",
|
|
195
|
+
"least-busy",
|
|
196
|
+
"simple-shuffle",
|
|
197
|
+
]
|
|
198
|
+
VALID_ROUTER_STRATEGIES = (
|
|
199
|
+
ROUTER_STRATEGIES_REQUIRING_REDIS_CACHE + ROUTER_STRATEGIES_NOT_REQUIRING_CACHE
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
MODELS_CONFIG_KEY = "models"
|
|
203
|
+
MODEL_GROUPS_CONFIG_KEY = "model_groups"
|
|
204
|
+
MODEL_GROUP_CONFIG_KEY = "model_group"
|
|
205
|
+
MODEL_GROUP_ID_CONFIG_KEY = "id"
|
|
206
|
+
|
|
207
|
+
EXTRA_PARAMETERS_KEY = "extra_parameters"
|
|
208
|
+
MODEL_GROUP_ID_KEY = "model_group_id"
|
|
209
|
+
MODEL_LIST_KEY = "model_list"
|
|
210
|
+
LITELLM_PARAMS_KEY = "litellm_params"
|
|
211
|
+
|
|
186
212
|
LLM_API_HEALTH_CHECK_ENV_VAR = "LLM_API_HEALTH_CHECK"
|
|
213
|
+
LLM_API_HEALTH_CHECK_DEFAULT_VALUE = "false"
|
|
187
214
|
|
|
188
215
|
AZURE_API_KEY_ENV_VAR = "AZURE_API_KEY"
|
|
189
216
|
AZURE_AD_TOKEN_ENV_VAR = "AZURE_AD_TOKEN"
|
|
@@ -191,6 +218,8 @@ AZURE_API_BASE_ENV_VAR = "AZURE_API_BASE"
|
|
|
191
218
|
AZURE_API_VERSION_ENV_VAR = "AZURE_API_VERSION"
|
|
192
219
|
AZURE_API_TYPE_ENV_VAR = "AZURE_API_TYPE"
|
|
193
220
|
|
|
221
|
+
AWS_REGION_NAME_CONFIG_KEY = "aws_region_name"
|
|
222
|
+
|
|
194
223
|
HUGGINGFACE_MULTIPROCESS_CONFIG_KEY = "multi_process"
|
|
195
224
|
HUGGINGFACE_CACHE_FOLDER_CONFIG_KEY = "cache_folder"
|
|
196
225
|
HUGGINGFACE_SHOW_PROGRESS_CONFIG_KEY = "show_progress"
|
|
@@ -211,6 +240,13 @@ OPENAI_PROVIDER = "openai"
|
|
|
211
240
|
AZURE_OPENAI_PROVIDER = "azure"
|
|
212
241
|
SELF_HOSTED_PROVIDER = "self-hosted"
|
|
213
242
|
HUGGINGFACE_LOCAL_EMBEDDING_PROVIDER = "huggingface_local"
|
|
243
|
+
RASA_PROVIDER = "rasa"
|
|
244
|
+
|
|
245
|
+
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
246
|
+
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
247
|
+
|
|
248
|
+
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
249
|
+
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
214
250
|
|
|
215
251
|
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
216
252
|
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
@@ -244,6 +280,3 @@ RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT = (
|
|
|
244
280
|
)
|
|
245
281
|
|
|
246
282
|
ROUTE_TO_CALM_SLOT = "route_session_to_calm"
|
|
247
|
-
|
|
248
|
-
ORIGINAL_VALUE = "original_value"
|
|
249
|
-
RESOLVED_VALUE = "resolved_value"
|
rasa/shared/core/constants.py
CHANGED
|
@@ -11,6 +11,7 @@ USER_INTENT_BACK = "back"
|
|
|
11
11
|
USER_INTENT_OUT_OF_SCOPE = "out_of_scope"
|
|
12
12
|
USER_INTENT_SESSION_START = "session_start"
|
|
13
13
|
USER_INTENT_SESSION_END = "session_end"
|
|
14
|
+
USER_INTENT_SILENCE_TIMEOUT = "silence_timeout"
|
|
14
15
|
SESSION_START_METADATA_SLOT = "session_started_metadata"
|
|
15
16
|
|
|
16
17
|
DEFAULT_INTENTS = [
|
|
@@ -19,6 +20,7 @@ DEFAULT_INTENTS = [
|
|
|
19
20
|
USER_INTENT_OUT_OF_SCOPE,
|
|
20
21
|
USER_INTENT_SESSION_START,
|
|
21
22
|
USER_INTENT_SESSION_END,
|
|
23
|
+
USER_INTENT_SILENCE_TIMEOUT,
|
|
22
24
|
constants.DEFAULT_NLU_FALLBACK_INTENT_NAME,
|
|
23
25
|
]
|
|
24
26
|
|
|
@@ -106,6 +108,11 @@ FLOW_HASHES_SLOT = "flow_hashes"
|
|
|
106
108
|
|
|
107
109
|
FLOW_SLOT_NAMES = [FLOW_HASHES_SLOT]
|
|
108
110
|
|
|
111
|
+
# slots for audio timeout
|
|
112
|
+
SLOT_SILENCE_TIMEOUT = "silence_timeout"
|
|
113
|
+
SILENCE_TIMEOUT_DEFAULT_VALUE = 6.0
|
|
114
|
+
SLOT_CONSECUTIVE_SILENCE_TIMEOUTS = "consecutive_silence_timeouts"
|
|
115
|
+
SILENCE_SLOTS = [SLOT_SILENCE_TIMEOUT, SLOT_CONSECUTIVE_SILENCE_TIMEOUTS]
|
|
109
116
|
# slots for knowledge base
|
|
110
117
|
SLOT_LISTED_ITEMS = "knowledge_base_listed_objects"
|
|
111
118
|
SLOT_LAST_OBJECT = "knowledge_base_last_object"
|
rasa/shared/core/domain.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import collections
|
|
4
4
|
import copy
|
|
5
5
|
import json
|
|
6
|
+
import math
|
|
6
7
|
import os
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
from functools import cached_property
|
|
@@ -57,6 +58,7 @@ from rasa.shared.core.events import SlotSet, UserUttered
|
|
|
57
58
|
from rasa.shared.core.slots import (
|
|
58
59
|
AnySlot,
|
|
59
60
|
CategoricalSlot,
|
|
61
|
+
FloatSlot,
|
|
60
62
|
ListSlot,
|
|
61
63
|
Slot,
|
|
62
64
|
TextSlot,
|
|
@@ -1082,6 +1084,7 @@ class Domain:
|
|
|
1082
1084
|
self._add_knowledge_base_slots()
|
|
1083
1085
|
self._add_categorical_slot_default_value()
|
|
1084
1086
|
self._add_session_metadata_slot()
|
|
1087
|
+
self._add_audio_slots()
|
|
1085
1088
|
|
|
1086
1089
|
def _add_categorical_slot_default_value(self) -> None:
|
|
1087
1090
|
"""Add a default value to all categorical slots.
|
|
@@ -1136,6 +1139,29 @@ class Domain:
|
|
|
1136
1139
|
)
|
|
1137
1140
|
)
|
|
1138
1141
|
|
|
1142
|
+
def _add_audio_slots(self) -> None:
|
|
1143
|
+
"""Add slots relevant for audio channels."""
|
|
1144
|
+
self.slots.append(
|
|
1145
|
+
FloatSlot(
|
|
1146
|
+
rasa.shared.core.constants.SLOT_SILENCE_TIMEOUT,
|
|
1147
|
+
mappings=[],
|
|
1148
|
+
influence_conversation=False,
|
|
1149
|
+
is_builtin=True,
|
|
1150
|
+
initial_value=rasa.shared.core.constants.SILENCE_TIMEOUT_DEFAULT_VALUE,
|
|
1151
|
+
max_value=math.inf,
|
|
1152
|
+
)
|
|
1153
|
+
)
|
|
1154
|
+
self.slots.append(
|
|
1155
|
+
FloatSlot(
|
|
1156
|
+
rasa.shared.core.constants.SLOT_CONSECUTIVE_SILENCE_TIMEOUTS,
|
|
1157
|
+
mappings=[],
|
|
1158
|
+
influence_conversation=False,
|
|
1159
|
+
is_builtin=True,
|
|
1160
|
+
initial_value=0.0,
|
|
1161
|
+
max_value=math.inf,
|
|
1162
|
+
)
|
|
1163
|
+
)
|
|
1164
|
+
|
|
1139
1165
|
def _add_knowledge_base_slots(self) -> None:
|
|
1140
1166
|
"""Add slots for the knowledge base action to slots.
|
|
1141
1167
|
|
rasa/shared/core/flows/flow.py
CHANGED
|
@@ -60,6 +60,8 @@ class Flow:
|
|
|
60
60
|
"""
|
|
61
61
|
file_path: Optional[str] = None
|
|
62
62
|
"""The path to the file where the flow is stored."""
|
|
63
|
+
persisted_slots: List[str] = field(default_factory=list)
|
|
64
|
+
"""The list of slots that should be persisted after the flow ends."""
|
|
63
65
|
|
|
64
66
|
@staticmethod
|
|
65
67
|
def from_json(
|
|
@@ -95,6 +97,7 @@ class Flow:
|
|
|
95
97
|
# If we are reading the flows in after training the file_path is part of
|
|
96
98
|
# data. When the model is trained, take the provided file_path.
|
|
97
99
|
file_path=data.get("file_path") if "file_path" in data else file_path,
|
|
100
|
+
persisted_slots=data.get("persisted_slots", []),
|
|
98
101
|
)
|
|
99
102
|
|
|
100
103
|
def get_full_name(self) -> str:
|
|
@@ -167,6 +170,8 @@ class Flow:
|
|
|
167
170
|
data["nlu_trigger"] = self.nlu_triggers.as_json()
|
|
168
171
|
if self.file_path:
|
|
169
172
|
data["file_path"] = self.file_path
|
|
173
|
+
if self.persisted_slots:
|
|
174
|
+
data["persisted_slots"] = self.persisted_slots
|
|
170
175
|
|
|
171
176
|
return data
|
|
172
177
|
|
|
@@ -234,12 +234,16 @@ class FlowsList:
|
|
|
234
234
|
[f for f in self.underlying_flows if not f.is_startable_only_via_link()]
|
|
235
235
|
)
|
|
236
236
|
|
|
237
|
-
def available_slot_names(
|
|
237
|
+
def available_slot_names(
|
|
238
|
+
self, ask_before_filling: Optional[bool] = None
|
|
239
|
+
) -> Set[str]:
|
|
238
240
|
"""Get all slot names collected by flows."""
|
|
239
241
|
return {
|
|
240
242
|
step.collect
|
|
241
243
|
for flow in self.underlying_flows
|
|
242
244
|
for step in flow.get_collect_steps()
|
|
245
|
+
if ask_before_filling is None
|
|
246
|
+
or step.ask_before_filling == ask_before_filling
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
def available_custom_actions(self) -> Set[str]:
|
|
@@ -279,6 +279,9 @@
|
|
|
279
279
|
},
|
|
280
280
|
"steps": {
|
|
281
281
|
"$ref": "#/$defs/steps"
|
|
282
|
+
},
|
|
283
|
+
"persisted_slots": {
|
|
284
|
+
"$ref": "#/$defs/persisted_slots"
|
|
282
285
|
}
|
|
283
286
|
}
|
|
284
287
|
},
|
|
@@ -288,6 +291,13 @@
|
|
|
288
291
|
"items": {
|
|
289
292
|
"type": "object"
|
|
290
293
|
}
|
|
294
|
+
},
|
|
295
|
+
"persisted_slots": {
|
|
296
|
+
"type": "array",
|
|
297
|
+
"schema_name": "list of slots",
|
|
298
|
+
"items": {
|
|
299
|
+
"type": "string"
|
|
300
|
+
}
|
|
291
301
|
}
|
|
292
302
|
}
|
|
293
303
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from typing import Set
|
|
2
|
+
from rasa.shared.utils.io import raise_deprecation_warning
|
|
3
|
+
|
|
4
|
+
RESET_PROPERTY_NAME = "reset_after_flow_ends"
|
|
5
|
+
PERSIST_PROPERTY_NAME = "persisted_slots"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def warn_deprecated_collect_step_config(flow_id: str, collect_step: str) -> None:
|
|
9
|
+
"""Warns about deprecated reset_after_flow_ends usage in collect steps."""
|
|
10
|
+
raise_deprecation_warning(
|
|
11
|
+
f"Configuring '{RESET_PROPERTY_NAME}' in collect step '{collect_step}' is "
|
|
12
|
+
f"deprecated and will be removed in Rasa Pro 4.0.0. In flow id '{flow_id}', "
|
|
13
|
+
f"please use the '{PERSIST_PROPERTY_NAME}' "
|
|
14
|
+
"property at the flow level instead."
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_duplicate_slot_persistence_config_error_message(
|
|
19
|
+
flow_id: str, collect_step: str
|
|
20
|
+
) -> str:
|
|
21
|
+
"""Returns an error message for duplicate slot persistence configuration."""
|
|
22
|
+
return (
|
|
23
|
+
f"Flow with id '{flow_id}' uses the '{RESET_PROPERTY_NAME}' property "
|
|
24
|
+
f"in collect step '{collect_step}' and also the "
|
|
25
|
+
f"'{PERSIST_PROPERTY_NAME}' property at the flow level. "
|
|
26
|
+
"Please use only one of the two configuration methods."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_invalid_slot_persistence_config_error_message(
|
|
31
|
+
flow_id: str, invalid_slots: Set[str]
|
|
32
|
+
) -> str:
|
|
33
|
+
"""Returns an error message for invalid slot persistence configuration."""
|
|
34
|
+
return (
|
|
35
|
+
f"Flow with id '{flow_id}' lists slot(s) '{invalid_slots}' in the "
|
|
36
|
+
f"'{PERSIST_PROPERTY_NAME}' property. However these slots "
|
|
37
|
+
f"are neither used in a collect step nor a set_slot step of the flow. "
|
|
38
|
+
f"Please remove such slots from the '{PERSIST_PROPERTY_NAME}' property."
|
|
39
|
+
)
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
import typing
|
|
5
5
|
from collections import defaultdict
|
|
6
|
+
from dataclasses import dataclass
|
|
6
7
|
from typing import Optional, Set, Text, List
|
|
7
8
|
|
|
8
9
|
from rasa.shared.constants import (
|
|
@@ -26,6 +27,12 @@ from rasa.shared.core.flows.steps.call import CallFlowStep
|
|
|
26
27
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
27
28
|
from rasa.shared.core.flows.steps.constants import CONTINUE_STEP_PREFIX, DEFAULT_STEPS
|
|
28
29
|
from rasa.shared.core.flows.steps.link import LinkFlowStep
|
|
30
|
+
from rasa.shared.core.flows.steps.set_slots import SetSlotsFlowStep
|
|
31
|
+
from rasa.shared.core.flows.utils import (
|
|
32
|
+
warn_deprecated_collect_step_config,
|
|
33
|
+
get_duplicate_slot_persistence_config_error_message,
|
|
34
|
+
get_invalid_slot_persistence_config_error_message,
|
|
35
|
+
)
|
|
29
36
|
from rasa.shared.exceptions import RasaException
|
|
30
37
|
|
|
31
38
|
if typing.TYPE_CHECKING:
|
|
@@ -379,6 +386,42 @@ class FlowIdNamingException(RasaException):
|
|
|
379
386
|
)
|
|
380
387
|
|
|
381
388
|
|
|
389
|
+
class DuplicateSlotPersistConfigException(RasaException):
|
|
390
|
+
"""Raised when a slot persist configuration is duplicated."""
|
|
391
|
+
|
|
392
|
+
def __init__(self, flow_id: str, collect_step: str) -> None:
|
|
393
|
+
"""Initializes the exception."""
|
|
394
|
+
self.flow_id = flow_id
|
|
395
|
+
self.collect_step = collect_step
|
|
396
|
+
|
|
397
|
+
def __str__(self) -> str:
|
|
398
|
+
"""Return a string representation of the exception."""
|
|
399
|
+
return get_duplicate_slot_persistence_config_error_message(
|
|
400
|
+
self.flow_id, self.collect_step
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class InvalidPersistSlotsException(RasaException):
|
|
405
|
+
"""Raised when a slot persist configuration is duplicated."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, flow_id: str, invalid_slots: Set[str]) -> None:
|
|
408
|
+
"""Initializes the exception."""
|
|
409
|
+
self.flow_id = flow_id
|
|
410
|
+
self.invalid_slots = invalid_slots
|
|
411
|
+
|
|
412
|
+
def __str__(self) -> str:
|
|
413
|
+
"""Return a string representation of the exception."""
|
|
414
|
+
return get_invalid_slot_persistence_config_error_message(
|
|
415
|
+
self.flow_id, self.invalid_slots
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dataclass
|
|
420
|
+
class ValidationResult:
|
|
421
|
+
is_valid: bool
|
|
422
|
+
invalid_slots: Set[str]
|
|
423
|
+
|
|
424
|
+
|
|
382
425
|
def validate_flow(flow: Flow) -> None:
|
|
383
426
|
"""Validates the flow configuration.
|
|
384
427
|
|
|
@@ -387,6 +430,8 @@ def validate_flow(flow: Flow) -> None:
|
|
|
387
430
|
- whether all next links point to existing steps
|
|
388
431
|
- whether all steps can be reached from the start step
|
|
389
432
|
"""
|
|
433
|
+
from rasa.cli.utils import is_skip_validation_flag_set
|
|
434
|
+
|
|
390
435
|
validate_flow_not_empty(flow)
|
|
391
436
|
validate_no_empty_step_sequences(flow)
|
|
392
437
|
validate_all_steps_next_property(flow)
|
|
@@ -397,6 +442,12 @@ def validate_flow(flow: Flow) -> None:
|
|
|
397
442
|
validate_slot_names_to_be_collected(flow)
|
|
398
443
|
validate_flow_id(flow)
|
|
399
444
|
|
|
445
|
+
if is_skip_validation_flag_set():
|
|
446
|
+
# we only want to run this validation if the --skip-validation flag is used
|
|
447
|
+
# during training because Flow Validation exceptions are raised one by one
|
|
448
|
+
# as opposed to all at once with the Validator class
|
|
449
|
+
validate_slot_persistence_configuration(flow)
|
|
450
|
+
|
|
400
451
|
|
|
401
452
|
def validate_flow_not_empty(flow: Flow) -> None:
|
|
402
453
|
"""Validate that the flow is not empty."""
|
|
@@ -637,3 +688,48 @@ def validate_flow_id(flow: Flow) -> None:
|
|
|
637
688
|
flow_re = re.compile(FLOW_ID_REGEX)
|
|
638
689
|
if not flow_re.search(flow.id):
|
|
639
690
|
raise FlowIdNamingException(flow.id)
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def validate_slot_persistence_configuration(flow: Flow) -> None:
|
|
694
|
+
"""Validates that slot persistence configuration is valid.
|
|
695
|
+
|
|
696
|
+
Only slots used in either a collect step or a set_slot step can be persisted
|
|
697
|
+
and the configuration can either be set at the flow level or the collect step level,
|
|
698
|
+
but not both.
|
|
699
|
+
|
|
700
|
+
Args:
|
|
701
|
+
flow: The flow to validate.
|
|
702
|
+
|
|
703
|
+
Raises:
|
|
704
|
+
DuplicateSlotPersistConfigException: If slot persist config is duplicated.
|
|
705
|
+
"""
|
|
706
|
+
|
|
707
|
+
def _is_persist_slots_valid(
|
|
708
|
+
persist_slots: List[str], flow_slots: Set[str]
|
|
709
|
+
) -> ValidationResult:
|
|
710
|
+
"""Validates that the slots that should be persisted are used in the flow."""
|
|
711
|
+
invalid_slots = set(persist_slots) - flow_slots
|
|
712
|
+
is_valid = False if invalid_slots else True
|
|
713
|
+
|
|
714
|
+
return ValidationResult(is_valid, invalid_slots)
|
|
715
|
+
|
|
716
|
+
flow_id = flow.id
|
|
717
|
+
persist_slots = flow.persisted_slots
|
|
718
|
+
has_flow_level_persistence = True if persist_slots else False
|
|
719
|
+
flow_slots = set()
|
|
720
|
+
|
|
721
|
+
for step in flow.steps_with_calls_resolved:
|
|
722
|
+
if isinstance(step, SetSlotsFlowStep):
|
|
723
|
+
flow_slots.update([slot["key"] for slot in step.slots])
|
|
724
|
+
elif isinstance(step, CollectInformationFlowStep):
|
|
725
|
+
flow_slots.add(step.collect)
|
|
726
|
+
if not step.reset_after_flow_ends:
|
|
727
|
+
collect_step = step.collect
|
|
728
|
+
warn_deprecated_collect_step_config(flow_id, collect_step)
|
|
729
|
+
if has_flow_level_persistence:
|
|
730
|
+
raise DuplicateSlotPersistConfigException(flow_id, collect_step)
|
|
731
|
+
|
|
732
|
+
if has_flow_level_persistence:
|
|
733
|
+
result = _is_persist_slots_valid(persist_slots, flow_slots)
|
|
734
|
+
if not result.is_valid:
|
|
735
|
+
raise InvalidPersistSlotsException(flow_id, result.invalid_slots)
|
rasa/shared/core/slots.py
CHANGED
|
@@ -193,6 +193,11 @@ class Slot(ABC):
|
|
|
193
193
|
data.update(self.persistence_info())
|
|
194
194
|
return rasa.shared.utils.io.get_dictionary_fingerprint(data)
|
|
195
195
|
|
|
196
|
+
def __eq__(self, other: Any) -> bool:
|
|
197
|
+
if not isinstance(other, Slot):
|
|
198
|
+
return False
|
|
199
|
+
return self.name == other.name and self.value == other.value
|
|
200
|
+
|
|
196
201
|
|
|
197
202
|
class FloatSlot(Slot):
|
|
198
203
|
"""A slot storing a float value."""
|
|
@@ -1,15 +1,133 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import itertools
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Iterable, Union, Text, Optional, List, Any, Tuple, Dict, Set
|
|
4
6
|
|
|
5
7
|
import numpy as np
|
|
6
8
|
import scipy.sparse
|
|
9
|
+
from safetensors.numpy import save_file, load_file
|
|
7
10
|
|
|
8
|
-
import rasa.shared.utils.io
|
|
9
11
|
import rasa.shared.nlu.training_data.util
|
|
12
|
+
import rasa.shared.utils.io
|
|
10
13
|
from rasa.shared.nlu.constants import FEATURE_TYPE_SEQUENCE, FEATURE_TYPE_SENTENCE
|
|
11
14
|
|
|
12
15
|
|
|
16
|
+
@dataclass
|
|
17
|
+
class FeatureMetadata:
|
|
18
|
+
data_type: str
|
|
19
|
+
attribute: str
|
|
20
|
+
origin: Union[str, List[str]]
|
|
21
|
+
is_sparse: bool
|
|
22
|
+
shape: tuple
|
|
23
|
+
safetensors_key: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def save_features(
|
|
27
|
+
features_dict: Dict[Text, List[Features]], file_name: str
|
|
28
|
+
) -> Dict[str, Any]:
|
|
29
|
+
"""Save a dictionary of Features lists to disk using safetensors.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
features_dict: Dictionary mapping strings to lists of Features objects
|
|
33
|
+
file_name: File to save the features to
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
The metadata to reconstruct the features.
|
|
37
|
+
"""
|
|
38
|
+
# All tensors are stored in a single safetensors file
|
|
39
|
+
tensors_to_save = {}
|
|
40
|
+
# Metadata will be stored separately
|
|
41
|
+
metadata = {}
|
|
42
|
+
|
|
43
|
+
for key, features_list in features_dict.items():
|
|
44
|
+
feature_metadata_list = []
|
|
45
|
+
|
|
46
|
+
for idx, feature in enumerate(features_list):
|
|
47
|
+
# Create a unique key for this tensor in the safetensors file
|
|
48
|
+
safetensors_key = f"{key}_{idx}"
|
|
49
|
+
|
|
50
|
+
# Convert sparse matrices to dense if needed
|
|
51
|
+
if feature.is_sparse():
|
|
52
|
+
# For sparse matrices, use the COO format
|
|
53
|
+
coo = feature.features.tocoo() # type:ignore[union-attr]
|
|
54
|
+
# Save data, row indices and col indices separately
|
|
55
|
+
tensors_to_save[f"{safetensors_key}_data"] = coo.data
|
|
56
|
+
tensors_to_save[f"{safetensors_key}_row"] = coo.row
|
|
57
|
+
tensors_to_save[f"{safetensors_key}_col"] = coo.col
|
|
58
|
+
else:
|
|
59
|
+
tensors_to_save[safetensors_key] = feature.features
|
|
60
|
+
|
|
61
|
+
# Store metadata
|
|
62
|
+
metadata_item = FeatureMetadata(
|
|
63
|
+
data_type=feature.type,
|
|
64
|
+
attribute=feature.attribute,
|
|
65
|
+
origin=feature.origin,
|
|
66
|
+
is_sparse=feature.is_sparse(),
|
|
67
|
+
shape=feature.features.shape,
|
|
68
|
+
safetensors_key=safetensors_key,
|
|
69
|
+
)
|
|
70
|
+
feature_metadata_list.append(vars(metadata_item))
|
|
71
|
+
|
|
72
|
+
metadata[key] = feature_metadata_list
|
|
73
|
+
|
|
74
|
+
# Save tensors
|
|
75
|
+
save_file(tensors_to_save, file_name)
|
|
76
|
+
|
|
77
|
+
return metadata
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def load_features(
|
|
81
|
+
filename: str, metadata: Dict[str, Any]
|
|
82
|
+
) -> Dict[Text, List[Features]]:
|
|
83
|
+
"""Load Features dictionary from disk.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
filename: File name of the safetensors file.
|
|
87
|
+
metadata: Metadata to reconstruct the features.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Dictionary mapping strings to lists of Features objects
|
|
91
|
+
"""
|
|
92
|
+
# Load tensors
|
|
93
|
+
tensors = load_file(filename)
|
|
94
|
+
|
|
95
|
+
# Reconstruct the features dictionary
|
|
96
|
+
features_dict: Dict[Text, List[Features]] = {}
|
|
97
|
+
|
|
98
|
+
for key, feature_metadata_list in metadata.items():
|
|
99
|
+
features_list = []
|
|
100
|
+
|
|
101
|
+
for meta in feature_metadata_list:
|
|
102
|
+
safetensors_key = meta["safetensors_key"]
|
|
103
|
+
|
|
104
|
+
if meta["is_sparse"]:
|
|
105
|
+
# Reconstruct sparse matrix from COO format
|
|
106
|
+
data = tensors[f"{safetensors_key}_data"]
|
|
107
|
+
row = tensors[f"{safetensors_key}_row"]
|
|
108
|
+
col = tensors[f"{safetensors_key}_col"]
|
|
109
|
+
|
|
110
|
+
features_matrix = scipy.sparse.coo_matrix(
|
|
111
|
+
(data, (row, col)), shape=tuple(meta["shape"])
|
|
112
|
+
).tocsr() # Convert back to CSR format
|
|
113
|
+
else:
|
|
114
|
+
features_matrix = tensors[safetensors_key]
|
|
115
|
+
|
|
116
|
+
# Reconstruct Features object
|
|
117
|
+
features = Features(
|
|
118
|
+
features=features_matrix,
|
|
119
|
+
feature_type=meta["data_type"],
|
|
120
|
+
attribute=meta["attribute"],
|
|
121
|
+
origin=meta["origin"],
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
features_list.append(features)
|
|
125
|
+
|
|
126
|
+
features_dict[key] = features_list
|
|
127
|
+
|
|
128
|
+
return features_dict
|
|
129
|
+
|
|
130
|
+
|
|
13
131
|
class Features:
|
|
14
132
|
"""Stores the features produced by any featurizer."""
|
|
15
133
|
|
|
@@ -107,8 +107,7 @@ class AzureOpenAIClientConfig:
|
|
|
107
107
|
|
|
108
108
|
@classmethod
|
|
109
109
|
def from_dict(cls, config: dict) -> "AzureOpenAIClientConfig":
|
|
110
|
-
"""
|
|
111
|
-
Initializes a dataclass from the passed config.
|
|
110
|
+
"""Initializes a dataclass from the passed config.
|
|
112
111
|
|
|
113
112
|
Args:
|
|
114
113
|
config: (dict) The config from which to initialize.
|
|
@@ -175,7 +174,10 @@ def is_azure_openai_config(config: dict) -> bool:
|
|
|
175
174
|
|
|
176
175
|
# Case: Configuration contains `deployment` key
|
|
177
176
|
# (specific to Azure OpenAI configuration)
|
|
178
|
-
if
|
|
177
|
+
if (
|
|
178
|
+
config.get(DEPLOYMENT_CONFIG_KEY) is not None
|
|
179
|
+
and config.get(PROVIDER_CONFIG_KEY) is None
|
|
180
|
+
):
|
|
179
181
|
return True
|
|
180
182
|
|
|
181
183
|
return False
|