rasa-pro 3.12.0.dev13__py3-none-any.whl → 3.12.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.
- README.md +10 -13
- rasa/anonymization/anonymization_rule_executor.py +16 -10
- rasa/cli/data.py +16 -0
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +1 -2
- rasa/cli/project_templates/calm/domain/remove_contact.yml +1 -2
- rasa/cli/project_templates/calm/domain/shared.yml +1 -4
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/utils.py +12 -0
- rasa/core/actions/action.py +84 -191
- rasa/core/actions/action_handle_digressions.py +35 -13
- rasa/core/actions/action_run_slot_rejections.py +16 -4
- rasa/core/channels/__init__.py +2 -0
- rasa/core/channels/studio_chat.py +19 -0
- rasa/core/channels/telegram.py +42 -24
- rasa/core/channels/voice_ready/utils.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +10 -4
- rasa/core/channels/voice_stream/asr/azure.py +14 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +20 -4
- rasa/core/channels/voice_stream/audiocodes.py +264 -0
- rasa/core/channels/voice_stream/browser_audio.py +4 -1
- rasa/core/channels/voice_stream/call_state.py +3 -0
- rasa/core/channels/voice_stream/genesys.py +6 -2
- rasa/core/channels/voice_stream/tts/azure.py +9 -1
- rasa/core/channels/voice_stream/tts/cartesia.py +14 -8
- rasa/core/channels/voice_stream/voice_channel.py +23 -2
- rasa/core/constants.py +2 -0
- rasa/core/nlg/contextual_response_rephraser.py +18 -1
- rasa/core/nlg/generator.py +83 -15
- rasa/core/nlg/response.py +6 -3
- rasa/core/nlg/translate.py +55 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flows/flow_executor.py +19 -7
- rasa/core/processor.py +71 -9
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +24 -6
- rasa/dialogue_understanding/commands/change_flow_command.py +20 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/clarify_command.py +29 -3
- rasa/dialogue_understanding/commands/command.py +1 -16
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/handle_digressions_command.py +1 -7
- rasa/dialogue_understanding/commands/human_handoff_command.py +20 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +20 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +24 -2
- rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +22 -2
- rasa/dialogue_understanding/commands/utils.py +71 -4
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_parser.py +15 -12
- rasa/dialogue_understanding/generator/constants.py +3 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -5
- rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +17 -3
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +2 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +77 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_default.jinja2 +68 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +84 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +522 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -310
- rasa/dialogue_understanding/patterns/collect_information.py +1 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +16 -0
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +39 -0
- rasa/dialogue_understanding/stack/utils.py +38 -0
- rasa/dialogue_understanding_test/du_test_case.py +58 -18
- rasa/dialogue_understanding_test/du_test_result.py +14 -10
- rasa/dialogue_understanding_test/io.py +14 -0
- rasa/e2e_test/assertions.py +6 -8
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +5 -1
- rasa/e2e_test/llm_judge_prompts/groundedness_prompt_template.jinja2 +4 -0
- rasa/e2e_test/utils/io.py +0 -37
- rasa/engine/graph.py +1 -0
- rasa/engine/language.py +140 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_recipe.py +2 -0
- rasa/engine/recipes/graph_recipe.py +2 -0
- rasa/engine/storage/local_model_storage.py +1 -0
- rasa/engine/storage/storage.py +4 -1
- rasa/llm_fine_tuning/conversations.py +1 -1
- rasa/model_manager/runner_service.py +7 -4
- rasa/model_manager/socket_bridge.py +7 -6
- rasa/shared/constants.py +15 -13
- rasa/shared/core/constants.py +2 -0
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +83 -19
- rasa/shared/core/flows/flows_yaml_schema.json +31 -3
- rasa/shared/core/flows/steps/collect.py +1 -36
- rasa/shared/core/flows/utils.py +28 -4
- rasa/shared/core/flows/validation.py +1 -1
- rasa/shared/core/slot_mappings.py +208 -5
- rasa/shared/core/slots.py +137 -1
- rasa/shared/core/trackers.py +74 -1
- rasa/shared/importers/importer.py +50 -2
- rasa/shared/nlu/training_data/schemas/responses.yml +19 -12
- rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +138 -3
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +3 -1
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +3 -1
- rasa/shared/providers/_configs/litellm_router_client_config.py +3 -1
- rasa/shared/providers/_configs/model_group_config.py +4 -2
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +3 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +3 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +3 -1
- rasa/shared/providers/constants.py +6 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +28 -3
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +3 -1
- rasa/shared/providers/llm/_base_litellm_client.py +42 -17
- rasa/shared/providers/llm/azure_openai_llm_client.py +81 -25
- rasa/shared/providers/llm/default_litellm_llm_client.py +3 -1
- rasa/shared/providers/llm/litellm_router_llm_client.py +29 -8
- rasa/shared/providers/llm/llm_client.py +23 -7
- rasa/shared/providers/llm/openai_llm_client.py +9 -3
- rasa/shared/providers/llm/rasa_llm_client.py +11 -2
- rasa/shared/providers/llm/self_hosted_llm_client.py +30 -11
- rasa/shared/providers/router/_base_litellm_router_client.py +3 -1
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/llm.py +33 -7
- rasa/shared/utils/pykwalify_extensions.py +24 -0
- rasa/shared/utils/schemas/domain.yml +26 -0
- rasa/telemetry.py +2 -1
- rasa/tracing/config.py +2 -0
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/instrumentation.py +36 -0
- rasa/tracing/instrumentation/metrics.py +41 -0
- rasa/tracing/metric_instrument_provider.py +40 -0
- rasa/validator.py +372 -7
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/METADATA +13 -14
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/RECORD +139 -124
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/entry_points.txt +0 -0
rasa/validator.py
CHANGED
|
@@ -16,9 +16,12 @@ import rasa.shared.utils.cli
|
|
|
16
16
|
import rasa.shared.utils.io
|
|
17
17
|
from rasa.core.channels import UserMessage
|
|
18
18
|
from rasa.dialogue_understanding.stack.frames import PatternFlowStackFrame
|
|
19
|
+
from rasa.engine.language import Language
|
|
19
20
|
from rasa.shared.constants import (
|
|
20
21
|
ASSISTANT_ID_DEFAULT_VALUE,
|
|
21
22
|
ASSISTANT_ID_KEY,
|
|
23
|
+
CONFIG_ADDITIONAL_LANGUAGES_KEY,
|
|
24
|
+
CONFIG_LANGUAGE_KEY,
|
|
22
25
|
CONFIG_MANDATORY_KEYS,
|
|
23
26
|
CONFIG_PIPELINE_KEY,
|
|
24
27
|
DOCS_URL_ACTIONS,
|
|
@@ -27,6 +30,7 @@ from rasa.shared.constants import (
|
|
|
27
30
|
DOCS_URL_FORMS,
|
|
28
31
|
DOCS_URL_RESPONSES,
|
|
29
32
|
REQUIRED_SLOTS_KEY,
|
|
33
|
+
RESPONSE_CONDITION,
|
|
30
34
|
UTTER_PREFIX,
|
|
31
35
|
)
|
|
32
36
|
from rasa.shared.core import constants
|
|
@@ -36,6 +40,7 @@ from rasa.shared.core.command_payload_reader import (
|
|
|
36
40
|
)
|
|
37
41
|
from rasa.shared.core.constants import (
|
|
38
42
|
KEY_ALLOW_NLU_CORRECTION,
|
|
43
|
+
SLOTS,
|
|
39
44
|
SlotMappingType,
|
|
40
45
|
)
|
|
41
46
|
from rasa.shared.core.domain import (
|
|
@@ -44,6 +49,7 @@ from rasa.shared.core.domain import (
|
|
|
44
49
|
)
|
|
45
50
|
from rasa.shared.core.events import ActionExecuted, ActiveLoop, UserUttered
|
|
46
51
|
from rasa.shared.core.flows import Flow, FlowsList
|
|
52
|
+
from rasa.shared.core.flows.constants import KEY_NAME, KEY_TRANSLATION
|
|
47
53
|
from rasa.shared.core.flows.flow_step_links import IfFlowStepLink
|
|
48
54
|
from rasa.shared.core.flows.steps.action import ActionFlowStep
|
|
49
55
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
@@ -56,12 +62,14 @@ from rasa.shared.core.flows.utils import (
|
|
|
56
62
|
warn_deprecated_collect_step_config,
|
|
57
63
|
)
|
|
58
64
|
from rasa.shared.core.generator import TrainingDataGenerator
|
|
65
|
+
from rasa.shared.core.slot_mappings import CoexistenceSystemType
|
|
59
66
|
from rasa.shared.core.slots import BooleanSlot, CategoricalSlot, ListSlot, Slot
|
|
60
67
|
from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
|
|
61
68
|
YAMLStoryReader,
|
|
62
69
|
)
|
|
63
70
|
from rasa.shared.core.training_data.structures import StoryGraph
|
|
64
71
|
from rasa.shared.data import create_regex_pattern_reader
|
|
72
|
+
from rasa.shared.exceptions import RasaException
|
|
65
73
|
from rasa.shared.importers.importer import TrainingDataImporter
|
|
66
74
|
from rasa.shared.nlu.constants import COMMANDS
|
|
67
75
|
from rasa.shared.nlu.training_data.message import Message
|
|
@@ -907,6 +915,16 @@ class Validator:
|
|
|
907
915
|
f"'{object_id}': {exception}"
|
|
908
916
|
),
|
|
909
917
|
)
|
|
918
|
+
elif object_id.startswith("utter_"):
|
|
919
|
+
structlogger.error(
|
|
920
|
+
"validator.validate_conditional_response_variation_predicates.error",
|
|
921
|
+
utter=object_id,
|
|
922
|
+
exception=exception,
|
|
923
|
+
event_info=(
|
|
924
|
+
f"Could not initialize the predicate found under response "
|
|
925
|
+
f"variation '{object_id}': {exception}"
|
|
926
|
+
),
|
|
927
|
+
)
|
|
910
928
|
else:
|
|
911
929
|
structlogger.error(
|
|
912
930
|
"validator.verify_predicates.flow_guard_predicate.error",
|
|
@@ -938,7 +956,7 @@ class Validator:
|
|
|
938
956
|
def _extract_slot_name_and_slot_value(
|
|
939
957
|
self,
|
|
940
958
|
predicate_syntax_tree: Any,
|
|
941
|
-
) ->
|
|
959
|
+
) -> Tuple[Optional[List[str]], Optional[Any]]:
|
|
942
960
|
"""Extract the slot name and slot value from the predicate syntax tree.
|
|
943
961
|
|
|
944
962
|
Args:
|
|
@@ -1043,15 +1061,15 @@ class Validator:
|
|
|
1043
1061
|
False, if validation failed, previous value of all_good, otherwise
|
|
1044
1062
|
"""
|
|
1045
1063
|
predicate_syntax_tree = self._extract_predicate_syntax_tree(predicate)
|
|
1046
|
-
|
|
1064
|
+
slot_namespace, slot_value = self._extract_slot_name_and_slot_value(
|
|
1047
1065
|
predicate_syntax_tree
|
|
1048
1066
|
)
|
|
1049
1067
|
|
|
1050
|
-
if
|
|
1068
|
+
if slot_namespace is None:
|
|
1051
1069
|
return all_good
|
|
1052
1070
|
|
|
1053
|
-
if
|
|
1054
|
-
slot_name =
|
|
1071
|
+
if slot_namespace[0] == "slots":
|
|
1072
|
+
slot_name = slot_namespace[1]
|
|
1055
1073
|
# slots.{{context.variable}} gets evaluated to `slots.None`,
|
|
1056
1074
|
# these predicates can only be validated during runtime
|
|
1057
1075
|
if slot_name == "None":
|
|
@@ -1272,6 +1290,165 @@ class Validator:
|
|
|
1272
1290
|
|
|
1273
1291
|
return all_good
|
|
1274
1292
|
|
|
1293
|
+
def _get_response_translation_warnings(self) -> list:
|
|
1294
|
+
"""Collect warnings for responses missing translations.
|
|
1295
|
+
|
|
1296
|
+
Returns:
|
|
1297
|
+
List of warnings for responses missing translations.
|
|
1298
|
+
"""
|
|
1299
|
+
additional_languages = self.config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY) or []
|
|
1300
|
+
response_warnings = []
|
|
1301
|
+
|
|
1302
|
+
for response_name, responses in self.domain.responses.items():
|
|
1303
|
+
provided_languages = set()
|
|
1304
|
+
# For each response variation, we check if the additional
|
|
1305
|
+
# languages are available in at least on variation
|
|
1306
|
+
for response in responses:
|
|
1307
|
+
translation = response.get(KEY_TRANSLATION) or {}
|
|
1308
|
+
for language_code in additional_languages:
|
|
1309
|
+
if translation.get(language_code):
|
|
1310
|
+
provided_languages.add(language_code)
|
|
1311
|
+
|
|
1312
|
+
missing_languages = [
|
|
1313
|
+
lang for lang in additional_languages if lang not in provided_languages
|
|
1314
|
+
]
|
|
1315
|
+
if missing_languages:
|
|
1316
|
+
language_code_str = ", ".join(missing_languages)
|
|
1317
|
+
response_warnings.append(
|
|
1318
|
+
{
|
|
1319
|
+
"event": (
|
|
1320
|
+
"validator.verify_translations.missing_response_translation"
|
|
1321
|
+
),
|
|
1322
|
+
"response": response_name,
|
|
1323
|
+
"missing_languages": missing_languages,
|
|
1324
|
+
"event_info": (
|
|
1325
|
+
f"The response '{response_name}' is "
|
|
1326
|
+
f"missing a translation for the following "
|
|
1327
|
+
f"languages: {language_code_str}."
|
|
1328
|
+
),
|
|
1329
|
+
}
|
|
1330
|
+
)
|
|
1331
|
+
return response_warnings
|
|
1332
|
+
|
|
1333
|
+
def _get_flow_translation_warnings(self) -> list:
|
|
1334
|
+
"""Collect warnings for flows missing translations.
|
|
1335
|
+
|
|
1336
|
+
Returns:
|
|
1337
|
+
List of warnings for flows missing translations.
|
|
1338
|
+
"""
|
|
1339
|
+
additional_languages = self.config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY) or []
|
|
1340
|
+
|
|
1341
|
+
flow_warnings = []
|
|
1342
|
+
for flow in self.flows.underlying_flows:
|
|
1343
|
+
required_field_translation = [KEY_NAME]
|
|
1344
|
+
missing_languages = []
|
|
1345
|
+
for language_code in additional_languages:
|
|
1346
|
+
translation = flow.translation.get(language_code)
|
|
1347
|
+
# If translation for the language code doesn't exist,
|
|
1348
|
+
# or the required fields are not set properly,
|
|
1349
|
+
# we add the language code to the list.
|
|
1350
|
+
if not translation or not all(
|
|
1351
|
+
getattr(translation, field, None)
|
|
1352
|
+
for field in required_field_translation
|
|
1353
|
+
):
|
|
1354
|
+
missing_languages.append(language_code)
|
|
1355
|
+
|
|
1356
|
+
if missing_languages:
|
|
1357
|
+
language_code_str = ", ".join(missing_languages)
|
|
1358
|
+
flow_warnings.append(
|
|
1359
|
+
{
|
|
1360
|
+
"event": (
|
|
1361
|
+
"validator.verify_translations.missing_flow_translation"
|
|
1362
|
+
),
|
|
1363
|
+
"flow": flow.id,
|
|
1364
|
+
"missing_languages": missing_languages,
|
|
1365
|
+
"event_info": (
|
|
1366
|
+
f"The flow '{flow.id}' is missing the translation for "
|
|
1367
|
+
f"the following languages: {language_code_str}."
|
|
1368
|
+
),
|
|
1369
|
+
}
|
|
1370
|
+
)
|
|
1371
|
+
return flow_warnings
|
|
1372
|
+
|
|
1373
|
+
def verify_config_language(self) -> bool:
|
|
1374
|
+
"""Verify that config languages are properly set up.
|
|
1375
|
+
|
|
1376
|
+
Returns:
|
|
1377
|
+
`True` if all languages are properly set up, `False` otherwise.
|
|
1378
|
+
|
|
1379
|
+
Raises:
|
|
1380
|
+
RasaException: If the default language is listed as an
|
|
1381
|
+
additional language or if the language code is invalid.
|
|
1382
|
+
"""
|
|
1383
|
+
language = self.config.get(CONFIG_LANGUAGE_KEY)
|
|
1384
|
+
additional_languages = self.config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY, [])
|
|
1385
|
+
|
|
1386
|
+
# Check if the default language is in the additional languages.
|
|
1387
|
+
if language in additional_languages:
|
|
1388
|
+
raise RasaException(
|
|
1389
|
+
f"The default language '{language}' is listed as an additional "
|
|
1390
|
+
f"language in the configuration file. Please remove it from "
|
|
1391
|
+
f"the list of additional languages."
|
|
1392
|
+
)
|
|
1393
|
+
|
|
1394
|
+
# Verify the language codes by initializing the Language class.
|
|
1395
|
+
for language_code in [language] + additional_languages:
|
|
1396
|
+
Language.from_language_code(language_code=language_code)
|
|
1397
|
+
|
|
1398
|
+
return True
|
|
1399
|
+
|
|
1400
|
+
def verify_translations(self, summary_mode: bool = False) -> bool:
|
|
1401
|
+
"""Checks for inconsistencies in translations.
|
|
1402
|
+
|
|
1403
|
+
Args:
|
|
1404
|
+
summary_mode: If True, logs a single aggregated warning per category;
|
|
1405
|
+
otherwise, logs each warning individually.
|
|
1406
|
+
|
|
1407
|
+
Returns:
|
|
1408
|
+
`True` if no inconsistencies were found, `False` otherwise.
|
|
1409
|
+
|
|
1410
|
+
Raises:
|
|
1411
|
+
Warning: Single warning per response or flow missing translations
|
|
1412
|
+
if `summary_mode` is `True`, otherwise one warning per missing translation.
|
|
1413
|
+
"""
|
|
1414
|
+
all_good = self.verify_config_language()
|
|
1415
|
+
|
|
1416
|
+
additional_languages = self.config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY, [])
|
|
1417
|
+
if not additional_languages:
|
|
1418
|
+
return all_good
|
|
1419
|
+
|
|
1420
|
+
response_warnings = self._get_response_translation_warnings()
|
|
1421
|
+
flow_warnings = self._get_flow_translation_warnings()
|
|
1422
|
+
|
|
1423
|
+
if summary_mode:
|
|
1424
|
+
if response_warnings:
|
|
1425
|
+
count = len(response_warnings)
|
|
1426
|
+
structlogger.warn(
|
|
1427
|
+
"validator.verify_translations.missing_response_translation_summary",
|
|
1428
|
+
count=count,
|
|
1429
|
+
event_info=(
|
|
1430
|
+
f"{count} response{' is' if count == 1 else 's are'} "
|
|
1431
|
+
f"missing translations for some languages. "
|
|
1432
|
+
"Run 'rasa data validate language' for details."
|
|
1433
|
+
),
|
|
1434
|
+
)
|
|
1435
|
+
if flow_warnings:
|
|
1436
|
+
count = len(flow_warnings)
|
|
1437
|
+
structlogger.warn(
|
|
1438
|
+
"validator.verify_translations.missing_flow_translation_summary",
|
|
1439
|
+
count=count,
|
|
1440
|
+
event_info=(
|
|
1441
|
+
f"{count} flow{' is' if count == 1 else 's are'} "
|
|
1442
|
+
f"missing translations for some languages. "
|
|
1443
|
+
"Run 'rasa data validate language' for details."
|
|
1444
|
+
),
|
|
1445
|
+
)
|
|
1446
|
+
else:
|
|
1447
|
+
for warning in response_warnings + flow_warnings:
|
|
1448
|
+
structlogger.warn(**warning)
|
|
1449
|
+
|
|
1450
|
+
return all_good
|
|
1451
|
+
|
|
1275
1452
|
def validate_button_payloads(self) -> bool:
|
|
1276
1453
|
"""Check if the response button payloads are valid."""
|
|
1277
1454
|
all_good = True
|
|
@@ -1410,6 +1587,8 @@ class Validator:
|
|
|
1410
1587
|
controlled_mappings, slot, all_good
|
|
1411
1588
|
)
|
|
1412
1589
|
|
|
1590
|
+
all_good = self._validate_controlled_mappings(slot, all_good)
|
|
1591
|
+
|
|
1413
1592
|
all_good = self._config_contains_nlu_command_adapter(
|
|
1414
1593
|
nlu_mappings, slot.name, all_good
|
|
1415
1594
|
)
|
|
@@ -1577,7 +1756,7 @@ class Validator:
|
|
|
1577
1756
|
collect_step = step.collect
|
|
1578
1757
|
flow_slots.add(collect_step)
|
|
1579
1758
|
if not step.reset_after_flow_ends:
|
|
1580
|
-
warn_deprecated_collect_step_config(
|
|
1759
|
+
warn_deprecated_collect_step_config()
|
|
1581
1760
|
|
|
1582
1761
|
if has_flow_level_persistence:
|
|
1583
1762
|
structlogger.error(
|
|
@@ -1638,10 +1817,15 @@ class Validator:
|
|
|
1638
1817
|
self.verify_predicates(),
|
|
1639
1818
|
]
|
|
1640
1819
|
)
|
|
1820
|
+
valid_translations = self.verify_translations(summary_mode=True)
|
|
1641
1821
|
valid_calm_slot_mappings = self.validate_CALM_slot_mappings()
|
|
1642
1822
|
|
|
1643
1823
|
all_good = (
|
|
1644
|
-
valid_responses
|
|
1824
|
+
valid_responses
|
|
1825
|
+
and valid_nlu
|
|
1826
|
+
and valid_flows
|
|
1827
|
+
and valid_translations
|
|
1828
|
+
and valid_calm_slot_mappings
|
|
1645
1829
|
)
|
|
1646
1830
|
|
|
1647
1831
|
return all_good
|
|
@@ -1765,3 +1949,184 @@ class Validator:
|
|
|
1765
1949
|
all_good = False
|
|
1766
1950
|
|
|
1767
1951
|
return all_good
|
|
1952
|
+
|
|
1953
|
+
def verify_slot_validation(self) -> bool:
|
|
1954
|
+
"""Validates the slot validation configuration in the domain file."""
|
|
1955
|
+
all_good = True
|
|
1956
|
+
|
|
1957
|
+
for slot in self.domain._user_slots:
|
|
1958
|
+
if slot.requires_validation():
|
|
1959
|
+
refill_utter = slot.validation.refill_utter # type: ignore[union-attr]
|
|
1960
|
+
if refill_utter and refill_utter not in self.domain.responses:
|
|
1961
|
+
self._log_slot_validation_error(
|
|
1962
|
+
slot.name, "refill utterance", refill_utter
|
|
1963
|
+
)
|
|
1964
|
+
all_good = False
|
|
1965
|
+
rejections = slot.validation.rejections # type: ignore[union-attr]
|
|
1966
|
+
for rejection in rejections:
|
|
1967
|
+
if rejection.utter not in self.domain.responses:
|
|
1968
|
+
self._log_slot_validation_error(
|
|
1969
|
+
slot.name, "rejection utterance", rejection.utter
|
|
1970
|
+
)
|
|
1971
|
+
all_good = False
|
|
1972
|
+
|
|
1973
|
+
return all_good
|
|
1974
|
+
|
|
1975
|
+
def _log_slot_validation_error(self, slot_name: str, key: str, value: str) -> None:
|
|
1976
|
+
structlogger.error(
|
|
1977
|
+
"validator.verify_slot_validation.response_not_in_domain",
|
|
1978
|
+
slot=slot_name,
|
|
1979
|
+
event_info=(
|
|
1980
|
+
f"The slot '{slot_name}' requires validation, "
|
|
1981
|
+
f"but the {key} '{value}' "
|
|
1982
|
+
f"is not listed in the domain responses. "
|
|
1983
|
+
f"Please add it to your domain file."
|
|
1984
|
+
),
|
|
1985
|
+
)
|
|
1986
|
+
|
|
1987
|
+
@staticmethod
|
|
1988
|
+
def _validate_controlled_mappings(slot: Slot, all_good: bool) -> bool:
|
|
1989
|
+
for mapping in slot.mappings:
|
|
1990
|
+
if (
|
|
1991
|
+
mapping.run_action_every_turn is not None
|
|
1992
|
+
and mapping.type != SlotMappingType.CONTROLLED
|
|
1993
|
+
):
|
|
1994
|
+
structlogger.error(
|
|
1995
|
+
"validator.validate_slot_mappings_in_CALM.run_action_every_turn_invalid",
|
|
1996
|
+
slot_name=slot.name,
|
|
1997
|
+
event_info=(
|
|
1998
|
+
f"The slot '{slot.name}' has a custom action "
|
|
1999
|
+
f"'{mapping.run_action_every_turn}' "
|
|
2000
|
+
f"defined in its slot mapping, "
|
|
2001
|
+
f"but the slot mapping type is not 'controlled'. "
|
|
2002
|
+
),
|
|
2003
|
+
)
|
|
2004
|
+
all_good = False
|
|
2005
|
+
|
|
2006
|
+
if (
|
|
2007
|
+
mapping.coexistence_system is not None
|
|
2008
|
+
and mapping.type != SlotMappingType.CONTROLLED
|
|
2009
|
+
):
|
|
2010
|
+
structlogger.error(
|
|
2011
|
+
"validator.validate_slot_mappings_in_CALM.coexistence_system_invalid",
|
|
2012
|
+
slot_name=slot.name,
|
|
2013
|
+
event_info=(
|
|
2014
|
+
f"The slot '{slot.name}' has a coexistence system "
|
|
2015
|
+
f"'{mapping.coexistence_system.value}' "
|
|
2016
|
+
f"defined in its slot mapping, "
|
|
2017
|
+
f"but the slot mapping type is not 'controlled'. "
|
|
2018
|
+
),
|
|
2019
|
+
)
|
|
2020
|
+
all_good = False
|
|
2021
|
+
|
|
2022
|
+
if (
|
|
2023
|
+
mapping.coexistence_system is not None
|
|
2024
|
+
and mapping.coexistence_system != CoexistenceSystemType.SHARED
|
|
2025
|
+
and slot.shared_for_coexistence
|
|
2026
|
+
):
|
|
2027
|
+
structlogger.error(
|
|
2028
|
+
"validator.validate_slot_mappings_in_CALM.shared_for_coexistence_invalid",
|
|
2029
|
+
slot_name=slot.name,
|
|
2030
|
+
event_info=(
|
|
2031
|
+
f"The slot '{slot.name}' has the `shared_for_coexistence` "
|
|
2032
|
+
f"property set to `True`, but the slot mapping `controlled` "
|
|
2033
|
+
f"type defines the `coexistence_system` property with a "
|
|
2034
|
+
f"value different to the expected `SHARED` value. "
|
|
2035
|
+
),
|
|
2036
|
+
)
|
|
2037
|
+
all_good = False
|
|
2038
|
+
|
|
2039
|
+
multiple_controlled_mappings = {
|
|
2040
|
+
mapping.coexistence_system.value
|
|
2041
|
+
for mapping in slot.mappings
|
|
2042
|
+
if mapping.type == SlotMappingType.CONTROLLED
|
|
2043
|
+
and mapping.coexistence_system is not None
|
|
2044
|
+
}
|
|
2045
|
+
contains_inconsistent_coexistence_system = len(multiple_controlled_mappings) > 1
|
|
2046
|
+
|
|
2047
|
+
if contains_inconsistent_coexistence_system:
|
|
2048
|
+
structlogger.error(
|
|
2049
|
+
"validator.validate_slot_mappings_in_CALM.inconsistent_multiple_mappings",
|
|
2050
|
+
slot_name=slot.name,
|
|
2051
|
+
event_info=(
|
|
2052
|
+
f"The slot '{slot.name}' has multiple `controlled` mappings "
|
|
2053
|
+
f"with different coexistence systems defined: "
|
|
2054
|
+
f"'{sorted(list(multiple_controlled_mappings))}'. "
|
|
2055
|
+
f"Please only define one coexistence system for the slot. "
|
|
2056
|
+
),
|
|
2057
|
+
)
|
|
2058
|
+
all_good = False
|
|
2059
|
+
|
|
2060
|
+
return all_good
|
|
2061
|
+
|
|
2062
|
+
def validate_conditional_response_variation_predicates(self) -> bool:
|
|
2063
|
+
"""Validate the conditional response variation predicates."""
|
|
2064
|
+
context = {"slots": {slot.name: None for slot in self.domain.slots}}
|
|
2065
|
+
all_good = True
|
|
2066
|
+
|
|
2067
|
+
for utter_name, variations in self.domain.responses.items():
|
|
2068
|
+
for variation in variations:
|
|
2069
|
+
condition = variation.get(RESPONSE_CONDITION)
|
|
2070
|
+
if not isinstance(condition, str):
|
|
2071
|
+
continue
|
|
2072
|
+
|
|
2073
|
+
predicate, all_good = self._construct_predicate(
|
|
2074
|
+
condition,
|
|
2075
|
+
utter_name,
|
|
2076
|
+
context,
|
|
2077
|
+
is_step=False,
|
|
2078
|
+
all_good=all_good,
|
|
2079
|
+
)
|
|
2080
|
+
if not predicate:
|
|
2081
|
+
continue
|
|
2082
|
+
|
|
2083
|
+
if not predicate.is_valid():
|
|
2084
|
+
structlogger.error(
|
|
2085
|
+
"validator.validate_conditional_response_variation_predicates.invalid_condition",
|
|
2086
|
+
utter=utter_name,
|
|
2087
|
+
event_info=(
|
|
2088
|
+
f"Detected invalid condition '{condition}' "
|
|
2089
|
+
f"for response variation '{utter_name}'. "
|
|
2090
|
+
f"Please make sure that all conditions are valid."
|
|
2091
|
+
),
|
|
2092
|
+
)
|
|
2093
|
+
all_good = False
|
|
2094
|
+
continue
|
|
2095
|
+
|
|
2096
|
+
predicate_syntax_tree = self._extract_predicate_syntax_tree(predicate)
|
|
2097
|
+
slot_namespace, _ = self._extract_slot_name_and_slot_value(
|
|
2098
|
+
predicate_syntax_tree
|
|
2099
|
+
)
|
|
2100
|
+
|
|
2101
|
+
if slot_namespace is not None and slot_namespace[0] != SLOTS:
|
|
2102
|
+
structlogger.error(
|
|
2103
|
+
"validator.validate_conditional_response_variation_predicates.invalid_namespace",
|
|
2104
|
+
utter=utter_name,
|
|
2105
|
+
event_info=(
|
|
2106
|
+
f"Detected invalid namespace '{slot_namespace[0]}' in "
|
|
2107
|
+
f"condition '{condition}' for response variation "
|
|
2108
|
+
f"'{utter_name}'. Please make sure that you're "
|
|
2109
|
+
f"using a valid namespace. "
|
|
2110
|
+
f"The current supported option is: 'slots'."
|
|
2111
|
+
),
|
|
2112
|
+
)
|
|
2113
|
+
all_good = False
|
|
2114
|
+
continue
|
|
2115
|
+
|
|
2116
|
+
if (
|
|
2117
|
+
slot_namespace is not None
|
|
2118
|
+
and slot_namespace[1] not in self.domain.slots
|
|
2119
|
+
):
|
|
2120
|
+
structlogger.error(
|
|
2121
|
+
"validator.validate_conditional_response_variation_predicates.invalid_slot",
|
|
2122
|
+
utter=utter_name,
|
|
2123
|
+
event_info=(
|
|
2124
|
+
f"Detected invalid slot '{slot_namespace[1]}' in "
|
|
2125
|
+
f"condition '{condition}' for response variation "
|
|
2126
|
+
f"'{utter_name}'. Please make sure that all slots "
|
|
2127
|
+
f"are specified in the domain file."
|
|
2128
|
+
),
|
|
2129
|
+
)
|
|
2130
|
+
all_good = False
|
|
2131
|
+
|
|
2132
|
+
return all_good
|
rasa/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rasa-pro
|
|
3
|
-
Version: 3.12.
|
|
3
|
+
Version: 3.12.0rc2
|
|
4
4
|
Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
|
|
5
5
|
Home-page: https://rasa.com
|
|
6
6
|
Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
|
|
@@ -31,6 +31,7 @@ Requires-Dist: aiogram (>=3.15,<3.16)
|
|
|
31
31
|
Requires-Dist: aiohttp (>=3.9.4,<3.10)
|
|
32
32
|
Requires-Dist: apscheduler (>=3.10,<3.11)
|
|
33
33
|
Requires-Dist: attrs (>=23.1,<23.2)
|
|
34
|
+
Requires-Dist: azure-identity (>=1.19.0,<1.20.0)
|
|
34
35
|
Requires-Dist: azure-storage-blob (>=12.16.0,<12.17.0)
|
|
35
36
|
Requires-Dist: boto3 (>=1.35.15,<1.36.0)
|
|
36
37
|
Requires-Dist: certifi (>=2024.07.04)
|
|
@@ -63,6 +64,7 @@ Requires-Dist: jsonschema (>=4.22)
|
|
|
63
64
|
Requires-Dist: keras (==2.14.0)
|
|
64
65
|
Requires-Dist: langchain (>=0.2.0,<0.3.0)
|
|
65
66
|
Requires-Dist: langchain-community (>=0.2.0,<0.3.0)
|
|
67
|
+
Requires-Dist: langcodes (>=3.5.0,<4.0.0)
|
|
66
68
|
Requires-Dist: litellm (>=1.52.6,<1.53.0)
|
|
67
69
|
Requires-Dist: matplotlib (>=3.7,<3.8)
|
|
68
70
|
Requires-Dist: mattermostwrapper (>=2.2,<2.3)
|
|
@@ -156,15 +158,14 @@ Description-Content-Type: text/markdown
|
|
|
156
158
|
|
|
157
159
|
<div align="center">
|
|
158
160
|
|
|
159
|
-
[](https://github.com/RasaHQ/rasa-private/actions)
|
|
160
161
|
[](https://sonarcloud.io/summary/new_code?id=RasaHQ_rasa)
|
|
161
|
-
[](https://rasa.com/docs/
|
|
162
|
+
[](https://rasa.com/docs/docs/pro/intro)
|
|
163
|
+

|
|
162
164
|
|
|
163
165
|
</div>
|
|
164
166
|
|
|
165
167
|
<hr />
|
|
166
168
|
|
|
167
|
-
|
|
168
169
|
Rasa Pro is a framework for building scalable, dynamic conversational AI assistants that integrate large language models (LLMs) to enable more contextually aware and agentic interactions. Whether you’re new to conversational AI or an experienced developer, Rasa Pro offers enhanced flexibility, control, and performance for mission-critical applications.
|
|
169
170
|
|
|
170
171
|
Building on the foundation of Rasa Open Source, Rasa Pro adds advanced features like CALM (Conversational AI with Language Models) and Dialogue Understanding (DU), which enable developers to shift from traditional intent-driven systems to LLM-based agents. This allows for more robust, responsive interactions that adhere strictly to business logic, while reducing risks like prompt injection and minimizing hallucinations.
|
|
@@ -177,20 +178,18 @@ Building on the foundation of Rasa Open Source, Rasa Pro adds advanced features
|
|
|
177
178
|
- **Robustness and Control:** Maintain strict adherence to business logic, preventing unwanted behaviors like prompt injection and hallucinations, leading to more reliable responses and secure interactions.
|
|
178
179
|
- **Built-in Security:** Safeguard sensitive data, control access, and ensure secure deployment, essential for production environments that demand high levels of security and compliance.
|
|
179
180
|
|
|
181
|
+
A [free developer license](https://rasa.com/docs/pro/intro/#who-rasa-pro-is-for) is available so you can explore and get to know Rasa Pro. It allows you to take your assistant live in production a limited capacity. A paid license is required for larger-scale production use, but all code is visible and can be customized as needed.
|
|
180
182
|
|
|
183
|
+
To get started right now, you can
|
|
181
184
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
To get started right now, you can
|
|
185
|
-
|
|
186
|
-
`pip install rasa-pro`
|
|
185
|
+
`pip install rasa-pro`
|
|
187
186
|
|
|
188
|
-
Check out our
|
|
187
|
+
Check out our
|
|
189
188
|
|
|
190
|
-
- [Rasa-pro Quickstart](https://rasa.com/docs/
|
|
191
|
-
- [Conversational AI with Language Models (CALM) conceptual rundown](https://rasa.com/docs/
|
|
192
|
-
- [Rasa Pro / CALM tutorial](https://rasa.com/docs/
|
|
193
|
-
- [Rasa pro changelog](https://rasa.com/docs/
|
|
189
|
+
- [Rasa-pro Quickstart](https://rasa.com/docs/learn/quickstart/pro),
|
|
190
|
+
- [Conversational AI with Language Models (CALM) conceptual rundown](https://rasa.com/docs/learn/concepts/calm),
|
|
191
|
+
- [Rasa Pro / CALM tutorial](https://rasa.com/docs/pro/tutorial), and
|
|
192
|
+
- [Rasa pro changelog](https://rasa.com/docs/reference/changelogs/rasa-pro-changelog)
|
|
194
193
|
|
|
195
194
|
for more. Also feel free to reach out to us on the [Rasa forum](https://forum.rasa.com/).
|
|
196
195
|
|