rasa-pro 3.12.0.dev13__py3-none-any.whl → 3.12.0rc1__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.

Files changed (128) hide show
  1. rasa/anonymization/anonymization_rule_executor.py +16 -10
  2. rasa/cli/data.py +16 -0
  3. rasa/cli/project_templates/calm/config.yml +2 -2
  4. rasa/cli/project_templates/calm/endpoints.yml +2 -2
  5. rasa/cli/utils.py +12 -0
  6. rasa/core/actions/action.py +84 -191
  7. rasa/core/actions/action_run_slot_rejections.py +16 -4
  8. rasa/core/channels/__init__.py +2 -0
  9. rasa/core/channels/studio_chat.py +19 -0
  10. rasa/core/channels/telegram.py +42 -24
  11. rasa/core/channels/voice_ready/utils.py +1 -1
  12. rasa/core/channels/voice_stream/asr/asr_engine.py +10 -4
  13. rasa/core/channels/voice_stream/asr/azure.py +14 -1
  14. rasa/core/channels/voice_stream/asr/deepgram.py +20 -4
  15. rasa/core/channels/voice_stream/audiocodes.py +264 -0
  16. rasa/core/channels/voice_stream/browser_audio.py +4 -1
  17. rasa/core/channels/voice_stream/call_state.py +3 -0
  18. rasa/core/channels/voice_stream/genesys.py +6 -2
  19. rasa/core/channels/voice_stream/tts/azure.py +9 -1
  20. rasa/core/channels/voice_stream/tts/cartesia.py +14 -8
  21. rasa/core/channels/voice_stream/voice_channel.py +23 -2
  22. rasa/core/constants.py +2 -0
  23. rasa/core/nlg/contextual_response_rephraser.py +18 -1
  24. rasa/core/nlg/generator.py +83 -15
  25. rasa/core/nlg/response.py +6 -3
  26. rasa/core/nlg/translate.py +55 -0
  27. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
  28. rasa/core/policies/flows/flow_executor.py +12 -5
  29. rasa/core/processor.py +72 -9
  30. rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
  31. rasa/dialogue_understanding/commands/cancel_flow_command.py +24 -6
  32. rasa/dialogue_understanding/commands/change_flow_command.py +20 -2
  33. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +20 -2
  34. rasa/dialogue_understanding/commands/clarify_command.py +29 -3
  35. rasa/dialogue_understanding/commands/command.py +1 -16
  36. rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
  37. rasa/dialogue_understanding/commands/human_handoff_command.py +20 -2
  38. rasa/dialogue_understanding/commands/knowledge_answer_command.py +20 -2
  39. rasa/dialogue_understanding/commands/prompt_command.py +94 -0
  40. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +20 -2
  41. rasa/dialogue_understanding/commands/set_slot_command.py +24 -2
  42. rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
  43. rasa/dialogue_understanding/commands/start_flow_command.py +20 -2
  44. rasa/dialogue_understanding/commands/utils.py +98 -4
  45. rasa/dialogue_understanding/generator/__init__.py +2 -0
  46. rasa/dialogue_understanding/generator/command_parser.py +15 -12
  47. rasa/dialogue_understanding/generator/constants.py +3 -0
  48. rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -5
  49. rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
  50. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +16 -2
  51. rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
  52. rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +2 -0
  53. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +77 -0
  54. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_default.jinja2 +68 -0
  55. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +84 -0
  56. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +460 -0
  57. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -310
  58. rasa/dialogue_understanding/patterns/collect_information.py +1 -1
  59. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +16 -0
  60. rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
  61. rasa/dialogue_understanding/processor/command_processor.py +39 -0
  62. rasa/dialogue_understanding_test/du_test_case.py +28 -8
  63. rasa/dialogue_understanding_test/du_test_result.py +13 -9
  64. rasa/dialogue_understanding_test/io.py +14 -0
  65. rasa/e2e_test/utils/io.py +0 -37
  66. rasa/engine/graph.py +1 -0
  67. rasa/engine/language.py +140 -0
  68. rasa/engine/recipes/config_files/default_config.yml +4 -0
  69. rasa/engine/recipes/default_recipe.py +2 -0
  70. rasa/engine/recipes/graph_recipe.py +2 -0
  71. rasa/engine/storage/local_model_storage.py +1 -0
  72. rasa/engine/storage/storage.py +4 -1
  73. rasa/model_manager/runner_service.py +7 -4
  74. rasa/model_manager/socket_bridge.py +7 -6
  75. rasa/shared/constants.py +15 -13
  76. rasa/shared/core/constants.py +2 -0
  77. rasa/shared/core/flows/constants.py +11 -0
  78. rasa/shared/core/flows/flow.py +83 -19
  79. rasa/shared/core/flows/flows_yaml_schema.json +31 -3
  80. rasa/shared/core/flows/steps/collect.py +1 -36
  81. rasa/shared/core/flows/utils.py +28 -4
  82. rasa/shared/core/flows/validation.py +1 -1
  83. rasa/shared/core/slot_mappings.py +208 -5
  84. rasa/shared/core/slots.py +131 -1
  85. rasa/shared/core/trackers.py +74 -1
  86. rasa/shared/importers/importer.py +50 -2
  87. rasa/shared/nlu/training_data/schemas/responses.yml +19 -12
  88. rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
  89. rasa/shared/providers/_configs/azure_openai_client_config.py +138 -3
  90. rasa/shared/providers/_configs/client_config.py +3 -1
  91. rasa/shared/providers/_configs/default_litellm_client_config.py +3 -1
  92. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +3 -1
  93. rasa/shared/providers/_configs/litellm_router_client_config.py +3 -1
  94. rasa/shared/providers/_configs/model_group_config.py +4 -2
  95. rasa/shared/providers/_configs/oauth_config.py +33 -0
  96. rasa/shared/providers/_configs/openai_client_config.py +3 -1
  97. rasa/shared/providers/_configs/rasa_llm_client_config.py +3 -1
  98. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +3 -1
  99. rasa/shared/providers/constants.py +6 -0
  100. rasa/shared/providers/embedding/azure_openai_embedding_client.py +28 -3
  101. rasa/shared/providers/embedding/litellm_router_embedding_client.py +3 -1
  102. rasa/shared/providers/llm/_base_litellm_client.py +42 -17
  103. rasa/shared/providers/llm/azure_openai_llm_client.py +81 -25
  104. rasa/shared/providers/llm/default_litellm_llm_client.py +3 -1
  105. rasa/shared/providers/llm/litellm_router_llm_client.py +29 -8
  106. rasa/shared/providers/llm/llm_client.py +23 -7
  107. rasa/shared/providers/llm/openai_llm_client.py +9 -3
  108. rasa/shared/providers/llm/rasa_llm_client.py +11 -2
  109. rasa/shared/providers/llm/self_hosted_llm_client.py +30 -11
  110. rasa/shared/providers/router/_base_litellm_router_client.py +3 -1
  111. rasa/shared/providers/router/router_client.py +3 -1
  112. rasa/shared/utils/constants.py +3 -0
  113. rasa/shared/utils/llm.py +30 -7
  114. rasa/shared/utils/pykwalify_extensions.py +24 -0
  115. rasa/shared/utils/schemas/domain.yml +26 -0
  116. rasa/telemetry.py +2 -1
  117. rasa/tracing/config.py +2 -0
  118. rasa/tracing/constants.py +12 -0
  119. rasa/tracing/instrumentation/instrumentation.py +36 -0
  120. rasa/tracing/instrumentation/metrics.py +41 -0
  121. rasa/tracing/metric_instrument_provider.py +40 -0
  122. rasa/validator.py +372 -7
  123. rasa/version.py +1 -1
  124. {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/METADATA +2 -1
  125. {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/RECORD +128 -113
  126. {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/NOTICE +0 -0
  127. {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/WHEEL +0 -0
  128. {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.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
- ) -> tuple:
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
- slot_name, slot_value = self._extract_slot_name_and_slot_value(
1064
+ slot_namespace, slot_value = self._extract_slot_name_and_slot_value(
1047
1065
  predicate_syntax_tree
1048
1066
  )
1049
1067
 
1050
- if slot_name is None:
1068
+ if slot_namespace is None:
1051
1069
  return all_good
1052
1070
 
1053
- if slot_name[0] == "slots":
1054
- slot_name = slot_name[1]
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(flow_id, collect_step)
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 and valid_nlu and valid_flows and valid_calm_slot_mappings
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,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.12.0.dev13"
3
+ __version__ = "3.12.0rc1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rasa-pro
3
- Version: 3.12.0.dev13
3
+ Version: 3.12.0rc1
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)