rasa-pro 3.13.3__py3-none-any.whl → 3.13.5__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 (69) hide show
  1. rasa/__main__.py +8 -0
  2. rasa/cli/data.py +8 -3
  3. rasa/cli/train.py +8 -0
  4. rasa/cli/utils.py +31 -15
  5. rasa/core/channels/inspector/dist/assets/{arc-371401b1.js → arc-0b11fe30.js} +1 -1
  6. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-3f126156.js → blockDiagram-38ab4fdb-9eef30a7.js} +1 -1
  7. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-12f22eb7.js → c4Diagram-3d4e48cf-03e94f28.js} +1 -1
  8. rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +1 -0
  9. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-03b1d386.js → classDiagram-70f12bd4-95c09eba.js} +1 -1
  10. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-84f69d63.js → classDiagram-v2-f2320105-38e8446c.js} +1 -1
  11. rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +1 -0
  12. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-ca47fd38.js → createText-2e5e7dd3-57dc3038.js} +1 -1
  13. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-f837ca8a.js → edges-e0da2a9e-4bac0545.js} +1 -1
  14. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-8717ac54.js → erDiagram-9861fffd-81795c90.js} +1 -1
  15. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-94f38b83.js → flowDb-956e92f1-89489ae6.js} +1 -1
  16. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-b616f9fb.js → flowDiagram-66a62f08-cd152627.js} +1 -1
  17. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +1 -0
  18. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f5d24bb8.js → flowchart-elk-definition-4a651766-3da369bc.js} +1 -1
  19. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-b43ba8d9.js → ganttDiagram-c361ad54-85ec16f8.js} +1 -1
  20. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-c3aafaa5.js → gitGraphDiagram-72cf32ee-495bc140.js} +1 -1
  21. rasa/core/channels/inspector/dist/assets/{graph-0d0a2c10.js → graph-1ec4d266.js} +1 -1
  22. rasa/core/channels/inspector/dist/assets/{index-3862675e-58ea0305.js → index-3862675e-0a0e97c9.js} +1 -1
  23. rasa/core/channels/inspector/dist/assets/{index-cce6f8a1.js → index-c804b295.js} +148 -148
  24. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b8f60461.js → infoDiagram-f8f76790-4d54bcde.js} +1 -1
  25. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-95be5545.js → journeyDiagram-49397b02-dc097114.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{layout-da885b9b.js → layout-1a08981e.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{line-f1c817d3.js → line-95f7f1d3.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/{linear-d42801e6.js → linear-97e69543.js} +1 -1
  29. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-a38923a6.js → mindmap-definition-fc14e90a-8c71ff03.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-ca6e71e9.js → pieDiagram-8a3498a8-f14c71c7.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b290dae9.js → quadrantDiagram-120e2f19-f1d3c9ff.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-03f02ceb.js → requirementDiagram-deff3bca-bfa2412f.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-c49eee40.js → sankeyDiagram-04a897e0-53f2c97b.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-b2cd6a3d.js → sequenceDiagram-704730f1-319d7c0e.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-e53a2028.js → stateDiagram-587899a1-76a09418.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e1982a03.js → stateDiagram-v2-d93cdb3a-a67f15d4.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-d0226ca5.js → styles-6aaf32cf-0654e7c3.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-0e21dc00.js → styles-9a916d00-1394bb9d.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-9588494e.js → styles-c10674c1-e4c5bdae.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-be478d4f.js → svgDrawCommon-08f97a94-50957104.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-74631749.js → timeline-definition-85554ec2-b0885a6a.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-a043552f.js → xychartDiagram-e933f94c-79e6541a.js} +1 -1
  43. rasa/core/channels/inspector/dist/index.html +1 -1
  44. rasa/core/channels/inspector/package.json +4 -3
  45. rasa/core/channels/inspector/yarn.lock +12 -12
  46. rasa/core/policies/enterprise_search_policy.py +15 -18
  47. rasa/dialogue_understanding/commands/correct_slots_command.py +38 -0
  48. rasa/dialogue_understanding/generator/command_parser.py +9 -13
  49. rasa/dialogue_understanding/processor/command_processor.py +127 -54
  50. rasa/dialogue_understanding/stack/utils.py +13 -3
  51. rasa/dialogue_understanding_test/validation.py +9 -10
  52. rasa/e2e_test/e2e_config.py +18 -11
  53. rasa/e2e_test/utils/validation.py +17 -19
  54. rasa/engine/validation.py +86 -91
  55. rasa/exceptions.py +26 -1
  56. rasa/shared/providers/_configs/default_litellm_client_config.py +3 -7
  57. rasa/shared/utils/cli.py +2 -0
  58. rasa/shared/utils/health_check/health_check.py +10 -14
  59. rasa/utils/tensorflow/transformer.py +3 -3
  60. rasa/validator.py +7 -5
  61. rasa/version.py +1 -1
  62. {rasa_pro-3.13.3.dist-info → rasa_pro-3.13.5.dist-info}/METADATA +1 -1
  63. {rasa_pro-3.13.3.dist-info → rasa_pro-3.13.5.dist-info}/RECORD +66 -66
  64. rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +0 -1
  65. rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +0 -1
  66. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +0 -1
  67. {rasa_pro-3.13.3.dist-info → rasa_pro-3.13.5.dist-info}/NOTICE +0 -0
  68. {rasa_pro-3.13.3.dist-info → rasa_pro-3.13.5.dist-info}/WHEEL +0 -0
  69. {rasa_pro-3.13.3.dist-info → rasa_pro-3.13.5.dist-info}/entry_points.txt +0 -0
@@ -1,13 +1,11 @@
1
- import sys
2
1
  from pathlib import Path
3
2
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
4
3
 
5
4
  import structlog
6
5
 
7
- import rasa.shared.utils.io
8
6
  from rasa.e2e_test.constants import SCHEMA_FILE_PATH
9
7
  from rasa.e2e_test.e2e_test_case import Fixture, Metadata
10
- from rasa.exceptions import ModelNotFound
8
+ from rasa.exceptions import ModelNotFound, ValidationError
11
9
  from rasa.shared.utils.yaml import read_schema_file
12
10
 
13
11
  if TYPE_CHECKING:
@@ -20,13 +18,11 @@ structlogger = structlog.get_logger()
20
18
  def validate_path_to_test_cases(path: str) -> None:
21
19
  """Validate that path to test cases exists."""
22
20
  if not Path(path).exists():
23
- rasa.shared.utils.io.raise_warning(
24
- f"Path to test cases does not exist: {path}. "
25
- f"Please provide a valid path to test cases. "
26
- f"Exiting...",
27
- UserWarning,
21
+ raise ValidationError(
22
+ code="e2e_test.utils.validation.invalid_test_case_path",
23
+ event_info=f"Path to test cases does not exist: {path}. "
24
+ f"Please provide a valid path to test cases. ",
28
25
  )
29
- sys.exit(1)
30
26
 
31
27
 
32
28
  def validate_test_case(
@@ -48,13 +44,11 @@ def validate_test_case(
48
44
  SystemExit: If the test case, fixtures, or metadata are not defined.
49
45
  """
50
46
  if test_case_name and not input_test_cases:
51
- rasa.shared.utils.io.raise_warning(
52
- f"Test case does not exist: {test_case_name}. "
53
- f"Please check for typos and provide a valid test case name. "
54
- f"Exiting...",
55
- UserWarning,
47
+ raise ValidationError(
48
+ code="e2e_test.utils.validation.invalid_test_case",
49
+ event_info=f"Test case does not exist: {test_case_name}. "
50
+ f"Please check for typos and provide a valid test case name. ",
56
51
  )
57
- sys.exit(1)
58
52
 
59
53
  all_good = True
60
54
  for test_case in input_test_cases:
@@ -63,7 +57,11 @@ def validate_test_case(
63
57
  all_good = all_good and all_good_fixtures and all_good_metadata
64
58
 
65
59
  if not all_good:
66
- sys.exit(1)
60
+ raise ValidationError(
61
+ code="e2e_test.utils.validation.missing_fixtures_or_metadata",
62
+ event_info="Some fixtures and/or metadata are missing - "
63
+ "see previous logs for additional details.",
64
+ )
67
65
 
68
66
 
69
67
  def validate_test_case_fixtures(
@@ -88,7 +86,7 @@ def validate_test_case_fixtures(
88
86
  for fixture_name in test_case.fixture_names:
89
87
  if fixture_name not in fixtures:
90
88
  structlogger.error(
91
- "validation.validate_test_case_fixtures",
89
+ "e2e_test.utils.validation.validate_test_case_fixtures",
92
90
  event_info=(
93
91
  f"Fixture '{fixture_name}' referenced in the "
94
92
  f"test case '{test_case.name}' is not defined."
@@ -117,7 +115,7 @@ def validate_test_case_metadata(
117
115
  all_good = True
118
116
  if test_case.metadata_name and test_case.metadata_name not in metadata:
119
117
  structlogger.error(
120
- "validation.validate_test_case_metadata.test_case_metadata",
118
+ "e2e_test.utils.validation.validate_test_case_metadata.test_case_metadata",
121
119
  event_info=(
122
120
  f"Metadata '{test_case.metadata_name}' referenced in "
123
121
  f"the test case '{test_case.name}' is not defined."
@@ -128,7 +126,7 @@ def validate_test_case_metadata(
128
126
  for step in test_case.steps:
129
127
  if step.metadata_name and step.metadata_name not in metadata:
130
128
  structlogger.error(
131
- "validation.validate_test_case_metadata.step_metadata",
129
+ "e2e_test.utils.validation.validate_test_case_metadata.step_metadata",
132
130
  event_info=(
133
131
  f"Metadata '{step.metadata_name}' referenced in the "
134
132
  f"step of the test case '{test_case.name}' is not defined."
rasa/engine/validation.py CHANGED
@@ -2,8 +2,8 @@ import dataclasses
2
2
  import inspect
3
3
  import logging
4
4
  import re
5
- import sys
6
5
  import typing
6
+ from collections import Counter
7
7
  from typing import (
8
8
  Any,
9
9
  Callable,
@@ -57,6 +57,7 @@ from rasa.engine.graph import (
57
57
  from rasa.engine.storage.resource import Resource
58
58
  from rasa.engine.storage.storage import ModelMetadata, ModelStorage
59
59
  from rasa.engine.training.fingerprinting import Fingerprintable
60
+ from rasa.exceptions import ValidationError
60
61
  from rasa.shared.constants import (
61
62
  API_BASE_CONFIG_KEY,
62
63
  API_KEY,
@@ -698,8 +699,8 @@ def _validate_intentless_policy_responses(
698
699
  return
699
700
 
700
701
  if not contains_intentless_policy_responses(flows, domain, story_graph):
701
- structlogger.error(
702
- "validation.intentless_policy.no_applicable_responses_found",
702
+ raise ValidationError(
703
+ code="engine.validation.intentless_policy.no_applicable_responses_found",
703
704
  event_info=(
704
705
  "IntentlessPolicy is configured, but no applicable responses are "
705
706
  "found. Please make sure that there are responses defined in the "
@@ -707,7 +708,6 @@ def _validate_intentless_policy_responses(
707
708
  "end-to-end stories in the training data."
708
709
  ),
709
710
  )
710
- sys.exit(1)
711
711
 
712
712
 
713
713
  def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
@@ -743,14 +743,13 @@ def validate_router_exclusivity(schema: GraphSchema) -> None:
743
743
  defined at the same time.
744
744
  """
745
745
  if schema.has_node(IntentBasedRouter) and schema.has_node(LLMBasedRouter):
746
- structlogger.error(
747
- "validation.coexistance.both_routers_defined",
746
+ raise ValidationError(
747
+ code="engine.validation.coexistance.both_routers_defined",
748
748
  event_info=(
749
749
  "Both LLMBasedRouter and IntentBasedRouter are in the config. "
750
750
  "Please use only one of them."
751
751
  ),
752
752
  )
753
- sys.exit(1)
754
753
 
755
754
 
756
755
  def validate_intent_based_router_position(schema: GraphSchema) -> None:
@@ -764,14 +763,13 @@ def validate_intent_based_router_position(schema: GraphSchema) -> None:
764
763
  and llm_command_generator_pos is not None
765
764
  and intent_based_router_pos > llm_command_generator_pos
766
765
  ):
767
- structlogger.error(
768
- "validation.coexistance.wrong_order_of_components",
766
+ raise ValidationError(
767
+ code="engine.validation.coexistance.wrong_order_of_components",
769
768
  event_info=(
770
769
  "IntentBasedRouter should come before "
771
- "a LLMBasedCommandGenerator in the pipeline."
770
+ "an LLMBasedCommandGenerator in the pipeline."
772
771
  ),
773
772
  )
774
- sys.exit(1)
775
773
 
776
774
 
777
775
  def validate_that_slots_are_defined_if_router_is_defined(
@@ -782,15 +780,14 @@ def validate_that_slots_are_defined_if_router_is_defined(
782
780
  router_present = schema.has_node(router_type)
783
781
  slot_has_issue = len(routing_slots) == 0 or routing_slots[0].type_name != "bool"
784
782
  if router_present and slot_has_issue:
785
- structlogger.error(
786
- f"validation.coexistance.{ROUTE_TO_CALM_SLOT}_not_in_domain",
783
+ raise ValidationError(
784
+ code=f"engine.validation.coexistance.{ROUTE_TO_CALM_SLOT}_not_in_domain",
787
785
  event_info=(
788
786
  f"{router_type.__name__} is in the config, but the slot "
789
787
  f"{ROUTE_TO_CALM_SLOT} is not in the domain or not of "
790
788
  f"type bool."
791
789
  ),
792
790
  )
793
- sys.exit(1)
794
791
 
795
792
 
796
793
  def validate_that_router_is_defined_if_router_slots_are_in_domain(
@@ -804,8 +801,8 @@ def validate_that_router_is_defined_if_router_slots_are_in_domain(
804
801
  if defined_router_slots and (
805
802
  not router_present or routing_slots[0].type_name != "bool"
806
803
  ):
807
- structlogger.error(
808
- f"validation.coexistance"
804
+ raise ValidationError(
805
+ code=f"engine.validation.coexistance"
809
806
  f".{ROUTE_TO_CALM_SLOT}_in_domain_with_no_router_defined",
810
807
  event_info=(
811
808
  f"The slot {ROUTE_TO_CALM_SLOT} is in the domain but the "
@@ -813,7 +810,6 @@ def validate_that_router_is_defined_if_router_slots_are_in_domain(
813
810
  f"the type of the slot is not bool."
814
811
  ),
815
812
  )
816
- sys.exit(1)
817
813
 
818
814
 
819
815
  def valid_nlu_entry_config(config: Optional[Dict[str, Any]]) -> bool:
@@ -842,14 +838,13 @@ def validate_configuration(
842
838
  if schema.has_node(IntentBasedRouter, include_subtypes=False):
843
839
  config = get_component_config(schema, IntentBasedRouter)
844
840
  if not valid_calm_entry_config(config) or not valid_nlu_entry_config(config):
845
- structlogger.error(
846
- "validation.coexistance.invalid_configuration",
841
+ raise ValidationError(
842
+ code="engine.validation.coexistance.invalid_configuration",
847
843
  event_info=(
848
844
  "The configuration of the IntentBasedRouter is invalid. "
849
- "Please check the documentation.",
845
+ "Please check the documentation."
850
846
  ),
851
847
  )
852
- sys.exit(1)
853
848
 
854
849
  if schema.has_node(LLMBasedRouter, include_subtypes=False):
855
850
  config = get_component_config(schema, LLMBasedRouter)
@@ -858,14 +853,13 @@ def validate_configuration(
858
853
  and NLU_ENTRY in config
859
854
  and not valid_nlu_entry_config(config)
860
855
  ):
861
- structlogger.error(
862
- "validation.coexistance.invalid_configuration",
856
+ raise ValidationError(
857
+ code="engine.validation.coexistance.invalid_configuration",
863
858
  event_info=(
864
859
  "The configuration of the LLMBasedRouter is invalid. "
865
- "Please check the documentation.",
860
+ "Please check the documentation."
866
861
  ),
867
862
  )
868
- sys.exit(1)
869
863
 
870
864
 
871
865
  def validate_coexistance_routing_setup(
@@ -892,7 +886,7 @@ def validate_coexistance_routing_setup(
892
886
  if faulty_flows_with_action_reset_routing:
893
887
  for flow in faulty_flows_with_action_reset_routing:
894
888
  structlogger.error(
895
- f"validation.coexistance.{ACTION_RESET_ROUTING}_present_in_flow"
889
+ f"engine.validation.coexistance.{ACTION_RESET_ROUTING}_present_in_flow"
896
890
  f"_without_router_or_{ROUTE_TO_CALM_SLOT}_slot",
897
891
  event_info=(
898
892
  f"The action - {ACTION_RESET_ROUTING} is used in the flow - "
@@ -900,7 +894,23 @@ def validate_coexistance_routing_setup(
900
894
  f" {ROUTE_TO_CALM_SLOT} are not defined.",
901
895
  ),
902
896
  )
903
- sys.exit(1)
897
+
898
+ flow_ids = [flow.id for flow in faulty_flows_with_action_reset_routing]
899
+ raise ValidationError(
900
+ code=(
901
+ "engine.validation.coexistance."
902
+ f"{ACTION_RESET_ROUTING}_present_in_flow_without_router_or_"
903
+ f"{ROUTE_TO_CALM_SLOT}_slot"
904
+ ),
905
+ event_info=(
906
+ f"The action '{ACTION_RESET_ROUTING}' is used in "
907
+ f"{len(flow_ids)} flow(s) "
908
+ f"({', '.join(flow_ids)}) without a router "
909
+ f"(LLMBasedRouter/IntentBasedRouter) or the "
910
+ f"'{ROUTE_TO_CALM_SLOT}' slot."
911
+ ),
912
+ flows=flow_ids, # any extra fields you want
913
+ )
904
914
 
905
915
  validate_router_exclusivity(schema)
906
916
  validate_intent_based_router_position(schema)
@@ -941,8 +951,8 @@ def _validate_component_model_client_config(
941
951
  model_group_ids.append(component_config[key][MODEL_GROUP_CONFIG_KEY])
942
952
 
943
953
  if len(component_config[key]) > 1:
944
- structlogger.error(
945
- "validation.validate_model_client_configuration_setup"
954
+ raise ValidationError(
955
+ code="engine.validation.validate_model_client_configuration_setup"
946
956
  ".only_model_group_reference_key_is_allowed",
947
957
  event_info=(
948
958
  f"You specified a '{MODEL_GROUP_CONFIG_KEY}' for the '{key}' "
@@ -954,15 +964,14 @@ def _validate_component_model_client_config(
954
964
  component_name=component_name or component_config["name"],
955
965
  component_client_config_key=key,
956
966
  )
957
- sys.exit(1)
958
967
  else:
959
968
  model_group_syntax_used.append(False)
960
969
 
961
970
  # check that any of the sensitive data keys is not set in config
962
971
  for secret_key in SENSITIVE_DATA:
963
972
  if secret_key in component_config[key]:
964
- structlogger.error(
965
- "validation.validate_model_client_configuration_setup"
973
+ raise ValidationError(
974
+ code="engine.validation.validate_model_client_configuration_setup"
966
975
  ".secret_key_not_allowed_in_the_config",
967
976
  event_info=(
968
977
  f"You specified '{secret_key}' in the config for "
@@ -974,7 +983,6 @@ def _validate_component_model_client_config(
974
983
  component_client_config_key=key,
975
984
  secret_key=secret_key,
976
985
  )
977
- sys.exit(1)
978
986
 
979
987
 
980
988
  def validate_model_client_configuration_setup_during_training_time(
@@ -1042,8 +1050,8 @@ def validate_model_client_configuration_setup_during_training_time(
1042
1050
  )
1043
1051
 
1044
1052
  if not is_uniform_bool_list(model_group_syntax_used):
1045
- structlogger.error(
1046
- "validation.validate_model_client_configuration_setup"
1053
+ raise ValidationError(
1054
+ code="engine.validation.validate_model_client_configuration_setup"
1047
1055
  ".inconsistent_use_of_model_group_syntax",
1048
1056
  event_info=(
1049
1057
  "Some of your components refer to an LLM using the "
@@ -1054,7 +1062,6 @@ def validate_model_client_configuration_setup_during_training_time(
1054
1062
  "and update your config."
1055
1063
  ),
1056
1064
  )
1057
- sys.exit(1)
1058
1065
 
1059
1066
  # Print a deprecation warning in case the old syntax is used.
1060
1067
  if len(model_group_syntax_used) > 0 and model_group_syntax_used[0] is False:
@@ -1070,8 +1077,8 @@ def validate_model_client_configuration_setup_during_training_time(
1070
1077
 
1071
1078
  endpoints = AvailableEndpoints.get_instance()
1072
1079
  if len(model_group_ids) > 0 and endpoints.model_groups is None:
1073
- structlogger.error(
1074
- "validation.validate_model_client_configuration_setup"
1080
+ raise ValidationError(
1081
+ code="engine.validation.validate_model_client_configuration_setup"
1075
1082
  ".referencing_model_group_but_none_are_defined",
1076
1083
  event_info=(
1077
1084
  "You are referring to (a) model group(s) in your "
@@ -1080,7 +1087,6 @@ def validate_model_client_configuration_setup_during_training_time(
1080
1087
  "group(s)."
1081
1088
  ),
1082
1089
  )
1083
- sys.exit(1)
1084
1090
 
1085
1091
  if endpoints.model_groups is None:
1086
1092
  return
@@ -1091,8 +1097,8 @@ def validate_model_client_configuration_setup_during_training_time(
1091
1097
 
1092
1098
  for model_group_id in model_group_ids:
1093
1099
  if model_group_id not in existing_model_group_ids:
1094
- structlogger.error(
1095
- "validation.validate_model_client_configuration_setup"
1100
+ raise ValidationError(
1101
+ code="engine.validation.validate_model_client_configuration_setup"
1096
1102
  ".referencing_undefined_model_group",
1097
1103
  event_info=(
1098
1104
  "One of your components is referring to the model group "
@@ -1104,7 +1110,6 @@ def validate_model_client_configuration_setup_during_training_time(
1104
1110
  referencing_model_group_id=model_group_id,
1105
1111
  existing_model_group_ids=existing_model_group_ids,
1106
1112
  )
1107
- sys.exit(1)
1108
1113
 
1109
1114
 
1110
1115
  def _validate_component_model_client_config_has_references_to_endpoints(
@@ -1139,8 +1144,8 @@ def _validate_component_model_client_config_has_references_to_endpoints(
1139
1144
  referencing_model_group_id = component_config[key][MODEL_GROUP_CONFIG_KEY]
1140
1145
 
1141
1146
  if endpoints.model_groups is None:
1142
- structlogger.error(
1143
- "validation.validate_model_client_config_correctly_references_endpoints"
1147
+ raise ValidationError(
1148
+ code="engine.validation.validate_model_client_config_correctly_references_endpoints"
1144
1149
  ".no_model_groups_defined",
1145
1150
  event_info=(
1146
1151
  f"Your {component_name or component_config.get('name') or ''} "
@@ -1154,7 +1159,6 @@ def _validate_component_model_client_config_has_references_to_endpoints(
1154
1159
  model_group_id=referencing_model_group_id,
1155
1160
  component_client_config_key=key,
1156
1161
  )
1157
- sys.exit(1)
1158
1162
 
1159
1163
  existing_model_group_ids = [
1160
1164
  model_group[MODEL_GROUP_ID_CONFIG_KEY]
@@ -1162,8 +1166,8 @@ def _validate_component_model_client_config_has_references_to_endpoints(
1162
1166
  ]
1163
1167
 
1164
1168
  if referencing_model_group_id not in existing_model_group_ids:
1165
- structlogger.error(
1166
- "validation.validate_model_client_config_correctly_references_endpoints"
1169
+ raise ValidationError(
1170
+ code="engine.validation.validate_model_client_config_correctly_references_endpoints"
1167
1171
  ".referenced_model_group_does_not_exist",
1168
1172
  event_info=(
1169
1173
  f"Your {component_name or component_config.get('name') or ''} "
@@ -1179,7 +1183,6 @@ def _validate_component_model_client_config_has_references_to_endpoints(
1179
1183
  existing_model_group_ids=existing_model_group_ids,
1180
1184
  component_client_config_key=key,
1181
1185
  )
1182
- sys.exit(1)
1183
1186
 
1184
1187
 
1185
1188
  def validate_model_client_configuration_setup_during_inference_time(
@@ -1223,14 +1226,18 @@ def _validate_unique_model_group_ids(model_groups: List[Dict[str, Any]]) -> None
1223
1226
  # Each model id must be unique within the model_groups
1224
1227
  model_ids = [model_group[MODEL_GROUP_ID_CONFIG_KEY] for model_group in model_groups]
1225
1228
  if len(model_ids) != len(set(model_ids)):
1226
- structlogger.error(
1227
- "validate_model_group_configuration_setup.non_unique_model_group_ids",
1229
+ counts = Counter(model_ids)
1230
+ duplicate_model_group_ids = {
1231
+ model_group_id for model_group_id, count in counts.items() if count > 1
1232
+ }
1233
+ raise ValidationError(
1234
+ code="engine.validation.validate_model_group_configuration_setup.non_unique_model_group_ids",
1228
1235
  event_info=(
1229
- "Each model group id must be unique. Please make sure that "
1230
- "the model group ids are unique in your endpoints.yml file."
1236
+ f"Duplicate model-group IDs found: "
1237
+ f"{', '.join(duplicate_model_group_ids)}. "
1238
+ f"Each model-group ID in endpoints.yml must be unique."
1231
1239
  ),
1232
1240
  )
1233
- sys.exit(1)
1234
1241
 
1235
1242
 
1236
1243
  def _validate_model_group_with_multiple_models(
@@ -1242,8 +1249,8 @@ def _validate_model_group_with_multiple_models(
1242
1249
  len(model_group[MODELS_CONFIG_KEY]) > 1
1243
1250
  and ROUTER_CONFIG_KEY not in model_group
1244
1251
  ):
1245
- structlogger.error(
1246
- "validate_model_group_configuration_setup.router_not_present",
1252
+ raise ValidationError(
1253
+ code="engine.validation.validate_model_group_configuration_setup.router_not_present",
1247
1254
  event_info=(
1248
1255
  f"You defined multiple models for the model group "
1249
1256
  f"'{model_group[MODEL_GROUP_ID_CONFIG_KEY]}', but no router. "
@@ -1253,7 +1260,6 @@ def _validate_model_group_with_multiple_models(
1253
1260
  ),
1254
1261
  model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
1255
1262
  )
1256
- sys.exit(1)
1257
1263
 
1258
1264
 
1259
1265
  def _validate_model_group_router_setting(
@@ -1266,8 +1272,8 @@ def _validate_model_group_router_setting(
1266
1272
 
1267
1273
  for model_config in model_group.get(MODELS_CONFIG_KEY, []):
1268
1274
  if USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY in model_config:
1269
- structlogger.error(
1270
- "validation.validate_model_group_configuration_setup"
1275
+ raise ValidationError(
1276
+ code="engine.validation.validate_model_group_configuration_setup"
1271
1277
  f".{USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY}_set_incorrectly",
1272
1278
  event_info=(
1273
1279
  f"You defined the '{USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY}' "
@@ -1280,14 +1286,13 @@ def _validate_model_group_router_setting(
1280
1286
  ),
1281
1287
  model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
1282
1288
  )
1283
- sys.exit(1)
1284
1289
 
1285
1290
  router_config = model_group[ROUTER_CONFIG_KEY]
1286
1291
  if ROUTING_STRATEGY_CONFIG_KEY in router_config:
1287
1292
  routing_strategy = router_config.get(ROUTING_STRATEGY_CONFIG_KEY)
1288
1293
  if routing_strategy and routing_strategy not in VALID_ROUTING_STRATEGIES:
1289
- structlogger.error(
1290
- "validation.validate_model_group_configuration_setup"
1294
+ raise ValidationError(
1295
+ code="engine.validation.validate_model_group_configuration_setup"
1291
1296
  ".invalid_routing_strategy",
1292
1297
  event_info=(
1293
1298
  f"The routing strategy '{routing_strategy}' you defined for "
@@ -1308,13 +1313,12 @@ def _validate_model_group_router_setting(
1308
1313
  ROUTING_STRATEGIES_NOT_REQUIRING_CACHE
1309
1314
  ),
1310
1315
  )
1311
- sys.exit(1)
1312
1316
  if (
1313
1317
  routing_strategy in ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE
1314
1318
  and REDIS_HOST_CONFIG_KEY not in router_config
1315
1319
  ):
1316
1320
  structlogger.warning(
1317
- "validation.routing_strategy.redis_host_not_defined",
1321
+ "engine.validation.routing_strategy.redis_host_not_defined",
1318
1322
  event_info=(
1319
1323
  f"The routing strategy '{routing_strategy}' requires a Redis "
1320
1324
  f"host to be defined. Without a Redis host, the system "
@@ -1349,8 +1353,8 @@ def _validate_usage_of_environment_variables_in_model_group_config(
1349
1353
  for key, value in model_config.items():
1350
1354
  if isinstance(value, str):
1351
1355
  if re.match(r"\${(\w+)}", value) and key not in allowed_env_vars:
1352
- structlogger.error(
1353
- "validation.validate_model_group_configuration_setup"
1356
+ raise ValidationError(
1357
+ code="engine.validation.validate_model_group_configuration_setup"
1354
1358
  ".invalid_use_of_environment_variables",
1355
1359
  event_info=(
1356
1360
  f"You defined '{key}' as environment variable in model "
@@ -1364,7 +1368,6 @@ def _validate_usage_of_environment_variables_in_model_group_config(
1364
1368
  key=key,
1365
1369
  allowed_keys_for_env_vars=allowed_env_vars,
1366
1370
  )
1367
- sys.exit(1)
1368
1371
 
1369
1372
 
1370
1373
  def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
@@ -1377,8 +1380,8 @@ def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
1377
1380
  if key in SENSITIVE_DATA:
1378
1381
  if isinstance(value, str):
1379
1382
  if not re.match(r"\${(\w+)}", value):
1380
- structlogger.error(
1381
- "validation.validate_model_group_configuration_setup"
1383
+ raise ValidationError(
1384
+ code="engine.validation.validate_model_group_configuration_setup"
1382
1385
  ".sensitive_key_string_value_must_be_set_as_env_var",
1383
1386
  event_info=(
1384
1387
  f"You defined the '{key}' in model group "
@@ -1389,10 +1392,9 @@ def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
1389
1392
  key=key,
1390
1393
  model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
1391
1394
  )
1392
- sys.exit(1)
1393
1395
  else:
1394
- structlogger.error(
1395
- "validation.validate_model_group_configuration_setup"
1396
+ raise ValidationError(
1397
+ code="engine.validation.validate_model_group_configuration_setup"
1396
1398
  ".sensitive_key_must_be_set_as_env_var",
1397
1399
  event_info=(
1398
1400
  f"You should define the '{key}' in model group "
@@ -1404,7 +1406,6 @@ def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
1404
1406
  key=key,
1405
1407
  model_group_id=model_group[MODEL_GROUP_ID_CONFIG_KEY],
1406
1408
  )
1407
- sys.exit(1)
1408
1409
 
1409
1410
 
1410
1411
  def validate_model_group_configuration_setup() -> None:
@@ -1436,14 +1437,11 @@ def validate_command_generator_exclusivity(schema: GraphSchema) -> None:
1436
1437
  )
1437
1438
 
1438
1439
  if count > 1:
1439
- structlogger.error(
1440
- "validation.command_generator.multiple_command_generator_defined",
1441
- event_info=(
1442
- "Multiple LLM based command generators are defined in the config. "
1443
- "Please use only one LLM based command generator."
1444
- ),
1440
+ raise ValidationError(
1441
+ code="engine.validation.command_generator.multiple_command_generator_defined",
1442
+ event_info="Multiple LLM based command generators are defined in "
1443
+ "the config. Please use only one LLM based command generator.",
1445
1444
  )
1446
- sys.exit(1)
1447
1445
 
1448
1446
 
1449
1447
  def validate_command_generator_setup(
@@ -1475,16 +1473,13 @@ def validate_api_type_config_key_usage(
1475
1473
  if API_TYPE_CONFIG_KEY in component_config[key]:
1476
1474
  api_type = component_config[key][API_TYPE_CONFIG_KEY]
1477
1475
  if api_type not in VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY:
1478
- structlogger.error(
1479
- "validation.component.api_type_config_key_invalid",
1480
- event_info=(
1481
- f"You specified '{API_TYPE_CONFIG_KEY}: {api_type}' for "
1482
- f"'{component_name or component_config['name']}', which is not "
1483
- f"allowed. "
1484
- f"The '{API_TYPE_CONFIG_KEY}' key can only be used for the "
1485
- f"following providers: {VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY}. "
1486
- f"For other providers, please use the '{PROVIDER_CONFIG_KEY}' key."
1487
- ),
1488
- )
1489
1476
  display_research_study_prompt()
1490
- sys.exit(1)
1477
+ raise ValidationError(
1478
+ code="engine.validation.component.api_type_config_key_invalid",
1479
+ event_info=f"You specified '{API_TYPE_CONFIG_KEY}: {api_type}' for "
1480
+ f"'{component_name or component_config['name']}', which is not "
1481
+ f"allowed. "
1482
+ f"The '{API_TYPE_CONFIG_KEY}' key can only be used for the "
1483
+ f"following providers: {VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY}. "
1484
+ f"For other providers, please use the '{PROVIDER_CONFIG_KEY}' key.",
1485
+ )
rasa/exceptions.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Text
2
+ from typing import Any, Dict, Text
3
3
 
4
4
  from packaging import version
5
5
 
@@ -51,6 +51,31 @@ class MissingDependencyException(RasaException):
51
51
  """Raised if a python package dependency is needed, but not installed."""
52
52
 
53
53
 
54
+ class DetailedRasaException(RasaException):
55
+ """Base class for exceptions that carry an error code and extra context."""
56
+
57
+ def __init__(self, *, code: str, event_info: str, **ctx: Any) -> None:
58
+ super().__init__(event_info)
59
+ self.code: str = code
60
+ self.info: str = event_info
61
+ self.ctx: Dict[str, Any] = ctx
62
+
63
+ def __str__(self) -> str:
64
+ return self.info
65
+
66
+
67
+ class HealthCheckError(DetailedRasaException):
68
+ """Raised when an error occurs during health checks."""
69
+
70
+
71
+ class EnterpriseSearchPolicyError(DetailedRasaException):
72
+ """Raised when an error occurs in EnterpriseSearchPolicy."""
73
+
74
+
75
+ class ValidationError(DetailedRasaException):
76
+ """Raised when an error occurs during validation."""
77
+
78
+
54
79
  @dataclass
55
80
  class PublishingError(RasaException):
56
81
  """Raised when publishing of an event fails.
@@ -5,7 +5,7 @@ from typing import Any, Dict
5
5
 
6
6
  import structlog
7
7
 
8
- import rasa.shared.utils.cli
8
+ from rasa.exceptions import ValidationError
9
9
  from rasa.shared.constants import (
10
10
  MODEL_CONFIG_KEY,
11
11
  MODEL_NAME_CONFIG_KEY,
@@ -124,9 +124,5 @@ class DefaultLiteLLMClientConfig:
124
124
  f"Unsupported parameter - {MODEL_NAME_CONFIG_KEY} is set. Please use "
125
125
  f"{MODEL_CONFIG_KEY} instead."
126
126
  )
127
- structlogger.error(
128
- "default_litellm_client_config.unsupported_parameter_in_config",
129
- event_info=event_info,
130
- config=config,
131
- )
132
- rasa.shared.utils.cli.print_error_and_exit(event_info)
127
+ error_code = "default_litellm_client_config.unsupported_parameter_in_config"
128
+ raise ValidationError(code=error_code, event_info=event_info, config=config)
rasa/shared/utils/cli.py CHANGED
@@ -65,6 +65,8 @@ def print_error(*args: Any) -> None:
65
65
 
66
66
  def print_error_and_exit(message: Text, exit_code: int = 1) -> NoReturn:
67
67
  """Print an error message and exit the application.
68
+ This function is intended only for the CLI module; library code
69
+ should raise an appropriate exception instead
68
70
 
69
71
  Args:
70
72
  message: The error message to be printed.