rasa-pro 3.11.3__py3-none-any.whl → 3.11.3a1.dev1__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 (77) hide show
  1. rasa/cli/studio/actions.py +48 -0
  2. rasa/cli/studio/studio.py +2 -0
  3. rasa/core/actions/direct_custom_actions_executor.py +31 -2
  4. rasa/core/channels/development_inspector.py +3 -0
  5. rasa/core/channels/inspector/dist/assets/{arc-632a63ec.js → arc-861ddd57.js} +1 -1
  6. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-081e0df4.js → c4Diagram-d0fbc5ce-921f02db.js} +1 -1
  7. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-3df0afc2.js → classDiagram-936ed81e-b436c4f8.js} +1 -1
  8. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-8c5ed31e.js → classDiagram-v2-c3cb15f1-511a23cb.js} +1 -1
  9. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-89c73b31.js → createText-62fc7601-ef476ecd.js} +1 -1
  10. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-4fc48c3e.js → edges-f2ad444c-f1878e0a.js} +1 -1
  11. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-907e0440.js → erDiagram-9d236eb7-fac75185.js} +1 -1
  12. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9ec53a3c.js → flowDb-1972c806-201c5bbc.js} +1 -1
  13. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-41da787a.js → flowDiagram-7ea5b25a-f904ae41.js} +1 -1
  14. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +1 -0
  15. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-ce370633.js → flowchart-elk-definition-abe16c3d-1813da66.js} +1 -1
  16. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-90a36523.js → ganttDiagram-9b5ea136-872af172.js} +1 -1
  17. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-41e1aa3f.js → gitGraphDiagram-99d0ae7c-34a0af5a.js} +1 -1
  18. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-e6f2af62.js → index-2c4b9a3b-42ba3e3d.js} +1 -1
  19. rasa/core/channels/inspector/dist/assets/{index-e793d777.js → index-37817b51.js} +3 -3
  20. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-8ceba4db.js → infoDiagram-736b4530-6b731386.js} +1 -1
  21. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-960d3809.js → journeyDiagram-df861f2b-e8579ac6.js} +1 -1
  22. rasa/core/channels/inspector/dist/assets/{layout-498807d8.js → layout-89e6403a.js} +1 -1
  23. rasa/core/channels/inspector/dist/assets/{line-eeccc4e2.js → line-dc73d3fc.js} +1 -1
  24. rasa/core/channels/inspector/dist/assets/{linear-8a078617.js → linear-f5b1d2bc.js} +1 -1
  25. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-396d17dd.js → mindmap-definition-beec6740-82cb74fa.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-dc9b5e1b.js → pieDiagram-dbbf0591-bdf5f29b.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-a08cba6d.js → quadrantDiagram-4d7f4fd6-c7a0cbe4.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-87242b9e.js → requirementDiagram-6fc4c22a-7ec5410f.js} +1 -1
  29. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-53f6f391.js → sankeyDiagram-8f13d901-caee5554.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-715c9c20.js → sequenceDiagram-b655622a-2935f8db.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-2e8fb31f.js → stateDiagram-59f0c015-8f5d9693.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-7e2d2aa0.js → stateDiagram-v2-2b26beab-d565d1de.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-4420cea6.js → styles-080da4f6-75ad421d.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-28676cf4.js → styles-3dcbcfbf-7e764226.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-cef936a6.js → styles-9c745c82-7a4e0e61.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-151251e9.js → svgDrawCommon-4835440b-4019d1bf.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-0d39bdb2.js → timeline-definition-5b62e21b-01ea12df.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-a03fa445.js → xychartDiagram-2b33534f-89407137.js} +1 -1
  39. rasa/core/channels/inspector/dist/index.html +1 -3
  40. rasa/core/channels/inspector/index.html +0 -2
  41. rasa/core/channels/inspector/src/App.tsx +4 -1
  42. rasa/core/channels/socketio.py +5 -0
  43. rasa/dialogue_understanding/generator/command_generator.py +126 -5
  44. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +28 -1
  45. rasa/dialogue_understanding/generator/nlu_command_adapter.py +3 -0
  46. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +9 -1
  47. rasa/dialogue_understanding/utils.py +14 -0
  48. rasa/dialogue_understanding_test/__init__.py +0 -0
  49. rasa/dialogue_understanding_test/constants.py +15 -0
  50. rasa/dialogue_understanding_test/du_test_case.py +118 -0
  51. rasa/dialogue_understanding_test/du_test_result.py +11 -0
  52. rasa/e2e_test/e2e_test_case.py +2 -1
  53. rasa/e2e_test/utils/e2e_yaml_utils.py +1 -1
  54. rasa/e2e_test/utils/io.py +1 -1
  55. rasa/e2e_test/utils/validation.py +100 -2
  56. rasa/engine/recipes/default_recipe.py +63 -49
  57. rasa/engine/recipes/graph_recipe.py +8 -7
  58. rasa/model_manager/runner_service.py +1 -0
  59. rasa/model_manager/socket_bridge.py +29 -7
  60. rasa/model_training.py +2 -1
  61. rasa/server.py +1 -37
  62. rasa/shared/constants.py +17 -6
  63. rasa/shared/nlu/constants.py +4 -0
  64. rasa/shared/utils/llm.py +1 -1
  65. rasa/shared/utils/yaml.py +6 -5
  66. rasa/studio/actions.py +147 -0
  67. rasa/studio/upload.py +19 -5
  68. rasa/telemetry.py +40 -33
  69. rasa/tracing/instrumentation/attribute_extractors.py +10 -9
  70. rasa/validator.py +32 -41
  71. rasa/version.py +1 -1
  72. {rasa_pro-3.11.3.dist-info → rasa_pro-3.11.3a1.dev1.dist-info}/METADATA +6 -6
  73. {rasa_pro-3.11.3.dist-info → rasa_pro-3.11.3a1.dev1.dist-info}/RECORD +76 -69
  74. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-8bea338b.js +0 -1
  75. {rasa_pro-3.11.3.dist-info → rasa_pro-3.11.3a1.dev1.dist-info}/NOTICE +0 -0
  76. {rasa_pro-3.11.3.dist-info → rasa_pro-3.11.3a1.dev1.dist-info}/WHEEL +0 -0
  77. {rasa_pro-3.11.3.dist-info → rasa_pro-3.11.3a1.dev1.dist-info}/entry_points.txt +0 -0
@@ -6,6 +6,7 @@ import structlog
6
6
 
7
7
  import rasa.shared.utils.io
8
8
  from rasa.e2e_test.constants import SCHEMA_FILE_PATH
9
+ from rasa.e2e_test.e2e_test_case import Fixture, Metadata
9
10
  from rasa.shared.utils.yaml import read_schema_file
10
11
 
11
12
  if TYPE_CHECKING:
@@ -27,8 +28,24 @@ def validate_path_to_test_cases(path: str) -> None:
27
28
  sys.exit(1)
28
29
 
29
30
 
30
- def validate_test_case(test_case_name: str, input_test_cases: List["TestCase"]) -> None:
31
- """Validate that test case exists."""
31
+ def validate_test_case(
32
+ test_case_name: str,
33
+ input_test_cases: List["TestCase"],
34
+ fixtures: Dict[str, Fixture],
35
+ metadata: Dict[str, Metadata],
36
+ ) -> None:
37
+ """
38
+ Validate the test case, its fixtures, and metadata.
39
+
40
+ Args:
41
+ test_case_name (str): The name of the test case to validate.
42
+ input_test_cases (List["TestCase"]): A list of test cases to validate.
43
+ fixtures (Dict[str, Fixture]): A dictionary of defined fixtures.
44
+ metadata (Dict[str, Metadata]): A dictionary of defined metadata.
45
+
46
+ Raises:
47
+ SystemExit: If the test case, fixtures, or metadata are not defined.
48
+ """
32
49
  if test_case_name and not input_test_cases:
33
50
  rasa.shared.utils.io.raise_warning(
34
51
  f"Test case does not exist: {test_case_name}. "
@@ -38,6 +55,87 @@ def validate_test_case(test_case_name: str, input_test_cases: List["TestCase"])
38
55
  )
39
56
  sys.exit(1)
40
57
 
58
+ all_good = True
59
+ for test_case in input_test_cases:
60
+ all_good_fixtures = validate_test_case_fixtures(test_case, fixtures)
61
+ all_good_metadata = validate_test_case_metadata(test_case, metadata)
62
+ all_good = all_good and all_good_fixtures and all_good_metadata
63
+
64
+ if not all_good:
65
+ sys.exit(1)
66
+
67
+
68
+ def validate_test_case_fixtures(
69
+ test_case: "TestCase", fixtures: Dict[str, Fixture]
70
+ ) -> bool:
71
+ """Validates that the fixtures used in the test case are defined.
72
+
73
+ Args:
74
+ test_case (TestCase): The test case to validate.
75
+ fixtures (Dict[str, Fixture]): A dictionary of defined fixtures.
76
+
77
+ Returns:
78
+ True if all fixtures used in the test case are defined, False otherwise.
79
+
80
+ Raises:
81
+ Logs an error if a fixture used in the test case is not defined.
82
+ """
83
+ all_good = True
84
+ if not test_case.fixture_names:
85
+ return all_good
86
+
87
+ for fixture_name in test_case.fixture_names:
88
+ if fixture_name not in fixtures:
89
+ structlogger.error(
90
+ "validation.validate_test_case_fixtures",
91
+ event_info=(
92
+ f"Fixture '{fixture_name}' referenced in the "
93
+ f"test case '{test_case.name}' is not defined."
94
+ ),
95
+ )
96
+ all_good = False
97
+ return all_good
98
+
99
+
100
+ def validate_test_case_metadata(
101
+ test_case: "TestCase", metadata: Dict[str, Metadata]
102
+ ) -> bool:
103
+ """
104
+ Validates that the metadata used in the test case and its steps are defined.
105
+
106
+ Args:
107
+ test_case (TestCase): The test case to validate.
108
+ metadata (Dict[str, Metadata]): A dictionary of defined metadata.
109
+
110
+ Returns:
111
+ True if all fixtures used in the test case are defined, False otherwise.
112
+
113
+ Raises:
114
+ Logs an error if metadata used in the test case or its steps is not defined.
115
+ """
116
+ all_good = True
117
+ if test_case.metadata_name and test_case.metadata_name not in metadata:
118
+ structlogger.error(
119
+ "validation.validate_test_case_metadata.test_case_metadata",
120
+ event_info=(
121
+ f"Metadata '{test_case.metadata_name}' referenced in "
122
+ f"the test case '{test_case.name}' is not defined."
123
+ ),
124
+ )
125
+ all_good = False
126
+
127
+ for step in test_case.steps:
128
+ if step.metadata_name and step.metadata_name not in metadata:
129
+ structlogger.error(
130
+ "validation.validate_test_case_metadata.step_metadata",
131
+ event_info=(
132
+ f"Metadata '{step.metadata_name}' referenced in the "
133
+ f"step of the test case '{test_case.name}' is not defined."
134
+ ),
135
+ )
136
+ all_good = False
137
+ return all_good
138
+
41
139
 
42
140
  def validate_model_path(model_path: Optional[str], parameter: str, default: str) -> str:
43
141
  """Validate the model path.
@@ -1,65 +1,71 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import copy
4
+ import dataclasses
4
5
  import enum
5
6
  import logging
6
7
  import math
7
8
  from enum import Enum
8
- from typing import Dict, Text, Any, Tuple, Type, Optional, List, Callable, Set, Union
9
-
10
- import dataclasses
9
+ from typing import Any, Callable, Dict, List, Optional, Set, Text, Tuple, Type, Union
11
10
 
11
+ import rasa.shared.constants
12
12
  from rasa.core.featurizers.precomputation import (
13
- CoreFeaturizationInputConverter,
14
13
  CoreFeaturizationCollector,
14
+ CoreFeaturizationInputConverter,
15
15
  )
16
- from rasa.graph_components.providers.flows_provider import FlowsProvider
16
+ from rasa.core.policies.ensemble import DefaultPolicyPredictionEnsemble
17
17
  from rasa.dialogue_understanding.processor.command_processor_component import (
18
18
  CommandProcessorComponent,
19
19
  )
20
- from rasa.shared.exceptions import FileNotFoundException
21
- from rasa.core.policies.ensemble import DefaultPolicyPredictionEnsemble
22
-
23
- from rasa.engine.graph import (
24
- GraphSchema,
25
- GraphComponent,
26
- SchemaNode,
27
- GraphModelConfiguration,
28
- )
29
20
  from rasa.engine.constants import (
21
+ PLACEHOLDER_ENDPOINTS,
30
22
  PLACEHOLDER_IMPORTER,
31
23
  PLACEHOLDER_MESSAGE,
32
24
  PLACEHOLDER_TRACKER,
33
- PLACEHOLDER_ENDPOINTS,
25
+ )
26
+ from rasa.engine.graph import (
27
+ GraphComponent,
28
+ GraphModelConfiguration,
29
+ GraphSchema,
30
+ SchemaNode,
34
31
  )
35
32
  from rasa.engine.recipes.recipe import Recipe
36
33
  from rasa.engine.storage.resource import Resource
37
34
  from rasa.graph_components.converters.nlu_message_converter import NLUMessageConverter
38
- from rasa.graph_components.providers.domain_provider import DomainProvider
39
- from rasa.graph_components.providers.forms_provider import FormsProvider
40
- from rasa.graph_components.providers.responses_provider import ResponsesProvider
41
35
  from rasa.graph_components.providers.domain_for_core_training_provider import (
42
36
  DomainForCoreTrainingProvider,
43
37
  )
38
+ from rasa.graph_components.providers.domain_provider import DomainProvider
39
+ from rasa.graph_components.providers.flows_provider import FlowsProvider
40
+ from rasa.graph_components.providers.forms_provider import FormsProvider
44
41
  from rasa.graph_components.providers.nlu_training_data_provider import (
45
42
  NLUTrainingDataProvider,
46
43
  )
44
+ from rasa.graph_components.providers.responses_provider import ResponsesProvider
47
45
  from rasa.graph_components.providers.rule_only_provider import RuleOnlyDataProvider
48
46
  from rasa.graph_components.providers.story_graph_provider import StoryGraphProvider
49
47
  from rasa.graph_components.providers.training_tracker_provider import (
50
48
  TrainingTrackerProvider,
51
49
  )
52
- import rasa.shared.constants
53
- from rasa.shared.exceptions import RasaException, InvalidConfigException
54
- from rasa.shared.constants import ASSISTANT_ID_KEY
50
+ from rasa.shared.constants import (
51
+ ASSISTANT_ID_KEY,
52
+ CONFIG_LANGUAGE_KEY,
53
+ CONFIG_NAME_KEY,
54
+ CONFIG_PIPELINE_KEY,
55
+ CONFIG_POLICIES_KEY,
56
+ )
55
57
  from rasa.shared.data import TrainingType
56
- from rasa.shared.utils.yaml import read_config_file
57
-
58
- from rasa.utils.tensorflow.constants import EPOCHS
58
+ from rasa.shared.exceptions import (
59
+ FileNotFoundException,
60
+ InvalidConfigException,
61
+ RasaException,
62
+ )
59
63
  from rasa.shared.utils.common import (
60
64
  class_from_module_path,
61
65
  transform_collection_to_sentence,
62
66
  )
67
+ from rasa.shared.utils.yaml import read_config_file
68
+ from rasa.utils.tensorflow.constants import EPOCHS
63
69
 
64
70
  logger = logging.getLogger(__name__)
65
71
 
@@ -67,13 +73,13 @@ logger = logging.getLogger(__name__)
67
73
  DEFAULT_PREDICT_KWARGS = dict(constructor_name="load", eager=True, is_target=False)
68
74
 
69
75
  COMMENTS_FOR_KEYS = {
70
- "pipeline": (
76
+ CONFIG_PIPELINE_KEY: (
71
77
  f"# # No configuration for the NLU pipeline was provided. The following "
72
78
  f"default pipeline was used to train your model.\n"
73
79
  f"# # If you'd like to customize it, uncomment and adjust the pipeline.\n"
74
80
  f"# # See {rasa.shared.constants.DOCS_URL_PIPELINE} for more information.\n"
75
81
  ),
76
- "policies": (
82
+ CONFIG_POLICIES_KEY: (
77
83
  f"# # No configuration for policies was provided. The following default "
78
84
  f"policies were used to train your model.\n"
79
85
  f"# # If you'd like to customize them, uncomment and adjust the policies.\n"
@@ -82,6 +88,10 @@ COMMENTS_FOR_KEYS = {
82
88
  }
83
89
 
84
90
 
91
+ GRAPH_NODE_RUN_PREFIX = "run_"
92
+ GRAPH_NODE_TRAIN_PREFIX = "train_"
93
+
94
+
85
95
  class DefaultV1RecipeRegisterException(RasaException):
86
96
  """If you register a class which is not of type `GraphComponent`."""
87
97
 
@@ -194,10 +204,12 @@ class DefaultV1Recipe(Recipe):
194
204
  ) -> GraphModelConfiguration:
195
205
  """Converts the default config to graphs (see interface for full docstring)."""
196
206
  self._use_core = (
197
- bool(config.get("policies")) and not training_type == TrainingType.NLU
207
+ bool(config.get(CONFIG_POLICIES_KEY))
208
+ and not training_type == TrainingType.NLU
198
209
  )
199
210
  self._use_nlu = (
200
- bool(config.get("pipeline")) and not training_type == TrainingType.CORE
211
+ bool(config.get(CONFIG_PIPELINE_KEY))
212
+ and not training_type == TrainingType.CORE
201
213
  )
202
214
 
203
215
  if not self._use_nlu and training_type == TrainingType.NLU:
@@ -232,9 +244,9 @@ class DefaultV1Recipe(Recipe):
232
244
  predict_schema=GraphSchema(predict_nodes),
233
245
  training_type=training_type,
234
246
  assistant_id=config.get(ASSISTANT_ID_KEY),
235
- language=config.get("language"),
247
+ language=config.get(CONFIG_LANGUAGE_KEY),
236
248
  core_target=core_target,
237
- nlu_target=f"run_{RegexMessageHandler.__name__}",
249
+ nlu_target=f"{GRAPH_NODE_RUN_PREFIX}{RegexMessageHandler.__name__}",
238
250
  )
239
251
 
240
252
  def _create_train_nodes(
@@ -317,7 +329,7 @@ class DefaultV1Recipe(Recipe):
317
329
  constructor_name="create",
318
330
  fn="provide",
319
331
  config={
320
- "language": train_config.get("language"),
332
+ "language": train_config.get(CONFIG_LANGUAGE_KEY),
321
333
  "persist": persist_nlu_data,
322
334
  },
323
335
  is_target=persist_nlu_data,
@@ -327,8 +339,8 @@ class DefaultV1Recipe(Recipe):
327
339
  last_run_node = "nlu_training_data_provider"
328
340
  preprocessors: List[Text] = []
329
341
 
330
- for idx, config in enumerate(train_config["pipeline"]):
331
- component_name = config.pop("name")
342
+ for idx, config in enumerate(train_config[CONFIG_PIPELINE_KEY]):
343
+ component_name = config.pop(CONFIG_NAME_KEY)
332
344
  component = self._from_registry(component_name)
333
345
  component_name = f"{component_name}{idx}"
334
346
 
@@ -451,7 +463,7 @@ class DefaultV1Recipe(Recipe):
451
463
  needs.update(self._get_model_provider_needs(train_nodes, component))
452
464
  needs["training_data"] = last_run_node
453
465
 
454
- train_node_name = f"train_{component_name}"
466
+ train_node_name = f"{GRAPH_NODE_TRAIN_PREFIX}{component_name}"
455
467
  train_nodes[train_node_name] = SchemaNode(
456
468
  needs=needs,
457
469
  uses=component,
@@ -469,10 +481,10 @@ class DefaultV1Recipe(Recipe):
469
481
  component_config: Dict[Text, Any],
470
482
  ) -> Dict[Text, Any]:
471
483
  from rasa.nlu.classifiers.mitie_intent_classifier import MitieIntentClassifier
472
- from rasa.nlu.extractors.mitie_entity_extractor import MitieEntityExtractor
473
484
  from rasa.nlu.classifiers.sklearn_intent_classifier import (
474
485
  SklearnIntentClassifier,
475
486
  )
487
+ from rasa.nlu.extractors.mitie_entity_extractor import MitieEntityExtractor
476
488
 
477
489
  cli_args_mapping: Dict[Type[GraphComponent], List[Text]] = {
478
490
  MitieIntentClassifier: ["num_threads"],
@@ -520,7 +532,7 @@ class DefaultV1Recipe(Recipe):
520
532
 
521
533
  needs["training_data"] = last_run_node
522
534
 
523
- node_name = f"run_{component_name}"
535
+ node_name = f"{GRAPH_NODE_RUN_PREFIX}{component_name}"
524
536
  train_nodes[node_name] = SchemaNode(
525
537
  needs=needs,
526
538
  uses=component_class,
@@ -627,8 +639,8 @@ class DefaultV1Recipe(Recipe):
627
639
  )
628
640
 
629
641
  policy_with_end_to_end_support_used = False
630
- for idx, config in enumerate(train_config["policies"]):
631
- component_name = config.pop("name")
642
+ for idx, config in enumerate(train_config[CONFIG_POLICIES_KEY]):
643
+ component_name = config.pop(CONFIG_NAME_KEY)
632
644
  component = self._from_registry(component_name)
633
645
 
634
646
  extra_config_from_cli = self._extra_config_from_cli(
@@ -647,7 +659,7 @@ class DefaultV1Recipe(Recipe):
647
659
  needs["precomputations"] = "end_to_end_features_provider"
648
660
  # during core training we use a stripped down version of the domain
649
661
  needs["domain"] = "domain_for_core_training_provider"
650
- train_nodes[f"train_{component_name}{idx}"] = SchemaNode(
662
+ train_nodes[f"{GRAPH_NODE_TRAIN_PREFIX}{component_name}{idx}"] = SchemaNode(
651
663
  needs=needs,
652
664
  uses=component.clazz,
653
665
  constructor_name="load" if self._is_finetuning else "create",
@@ -722,7 +734,9 @@ class DefaultV1Recipe(Recipe):
722
734
  if self._use_core:
723
735
  domain_needs["domain"] = "domain_provider"
724
736
 
725
- regex_handler_node_name = f"run_{RegexMessageHandler.__name__}"
737
+ regex_handler_node_name = (
738
+ f"{GRAPH_NODE_RUN_PREFIX}{RegexMessageHandler.__name__}"
739
+ )
726
740
  predict_nodes[regex_handler_node_name] = SchemaNode(
727
741
  **DEFAULT_PREDICT_KWARGS,
728
742
  needs={"messages": last_run_nlu_node, **domain_needs},
@@ -762,8 +776,8 @@ class DefaultV1Recipe(Recipe):
762
776
  resource=Resource("domain_provider"),
763
777
  )
764
778
 
765
- for idx, config in enumerate(predict_config["pipeline"]):
766
- component_name = config.pop("name")
779
+ for idx, config in enumerate(predict_config[CONFIG_PIPELINE_KEY]):
780
+ component_name = config.pop(CONFIG_NAME_KEY)
767
781
  component = self._from_registry(component_name)
768
782
  component_name = f"{component_name}{idx}"
769
783
  if self.ComponentType.MODEL_LOADER in component.types:
@@ -830,10 +844,10 @@ class DefaultV1Recipe(Recipe):
830
844
  item_config: Dict[Text, Any],
831
845
  from_resource: bool = False,
832
846
  ) -> Text:
833
- train_node_name = f"run_{node_name}"
847
+ train_node_name = f"{GRAPH_NODE_RUN_PREFIX}{node_name}"
834
848
  resource = None
835
849
  if from_resource:
836
- train_node_name = f"train_{node_name}"
850
+ train_node_name = f"{GRAPH_NODE_TRAIN_PREFIX}{node_name}"
837
851
  resource = Resource(train_node_name)
838
852
 
839
853
  return self._add_nlu_predict_node(
@@ -852,7 +866,7 @@ class DefaultV1Recipe(Recipe):
852
866
  component_name: Text,
853
867
  last_run_node: Text,
854
868
  ) -> Text:
855
- node_name = f"run_{component_name}"
869
+ node_name = f"{GRAPH_NODE_RUN_PREFIX}{component_name}"
856
870
 
857
871
  needs = self._get_needs_from_args(node.uses, "process")
858
872
  needs.update(self._get_model_provider_needs(predict_nodes, node.uses))
@@ -919,12 +933,12 @@ class DefaultV1Recipe(Recipe):
919
933
  rule_policy_resource = None
920
934
  policies: List[Text] = []
921
935
 
922
- for idx, config in enumerate(predict_config["policies"]):
923
- component_name = config.pop("name")
936
+ for idx, config in enumerate(predict_config[CONFIG_POLICIES_KEY]):
937
+ component_name = config.pop(CONFIG_NAME_KEY)
924
938
  component = self._from_registry(component_name)
925
939
 
926
- train_node_name = f"train_{component_name}{idx}"
927
- node_name = f"run_{component_name}{idx}"
940
+ train_node_name = f"{GRAPH_NODE_TRAIN_PREFIX}{component_name}{idx}"
941
+ node_name = f"{GRAPH_NODE_RUN_PREFIX}{component_name}{idx}"
928
942
 
929
943
  from rasa.core.policies.rule_policy import RulePolicy
930
944
 
@@ -1,16 +1,17 @@
1
1
  import logging
2
+ from typing import Any, Dict, Text, Tuple
2
3
 
4
+ from rasa.engine.graph import GraphModelConfiguration, GraphSchema
3
5
  from rasa.engine.recipes.recipe import Recipe
4
- from rasa.engine.graph import GraphModelConfiguration
5
- from rasa.shared.constants import DOCS_URL_GRAPH_RECIPE, ASSISTANT_ID_KEY
6
+ from rasa.shared.constants import (
7
+ ASSISTANT_ID_KEY,
8
+ CONFIG_LANGUAGE_KEY,
9
+ DOCS_URL_GRAPH_RECIPE,
10
+ )
6
11
  from rasa.shared.data import TrainingType
7
12
  from rasa.shared.exceptions import InvalidConfigException
8
13
  from rasa.shared.utils.common import mark_as_experimental_feature
9
14
  from rasa.shared.utils.io import raise_warning
10
- from rasa.engine.graph import GraphSchema
11
-
12
- from typing import Dict, Text, Any, Tuple
13
-
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
@@ -72,7 +73,7 @@ class GraphV1Recipe(Recipe):
72
73
  predict_schema=GraphSchema.from_dict(config.get("predict_schema")),
73
74
  training_type=training_type,
74
75
  assistant_id=config.get(ASSISTANT_ID_KEY),
75
- language=config.get("language"),
76
+ language=config.get(CONFIG_LANGUAGE_KEY),
76
77
  core_target=core_target,
77
78
  nlu_target=nlu_target,
78
79
  )
@@ -207,6 +207,7 @@ def start_bot_process(
207
207
  "--credentials",
208
208
  f"{bot_base_path}/credentials.yml",
209
209
  "--debug",
210
+ "--inspect",
210
211
  f"--port={port}",
211
212
  "--model",
212
213
  f"{bot_base_path}/models",
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from typing import Any, Dict, Optional
2
3
 
3
4
  from socketio import AsyncServer
@@ -9,12 +10,21 @@ from rasa.model_manager.studio_jwt_auth import (
9
10
  UserToServiceAuthenticationError,
10
11
  authenticate_user_to_service,
11
12
  )
13
+ from dataclasses import dataclass
12
14
 
13
15
  structlogger = structlog.get_logger()
14
16
 
15
17
 
18
+ @dataclass
19
+ class SocketProxyClient:
20
+ """Store information about a running bot."""
21
+
22
+ user_id: str
23
+ socket: AsyncClient
24
+
25
+
16
26
  # A simple in-memory store for active chat connections to studio frontend
17
- socket_proxy_clients = {}
27
+ socket_proxy_clients: Dict[str, SocketProxyClient] = {}
18
28
 
19
29
 
20
30
  async def socketio_websocket_traffic_wrapper(
@@ -31,7 +41,7 @@ async def socketio_websocket_traffic_wrapper(
31
41
  return False
32
42
 
33
43
  try:
34
- authenticate_user_to_service(auth_token)
44
+ user_info = authenticate_user_to_service(auth_token)
35
45
  structlogger.debug("model_runner.user_authenticated_successfully", sid=sid)
36
46
  except UserToServiceAuthenticationError as error:
37
47
  structlogger.error(
@@ -60,7 +70,9 @@ async def socketio_websocket_traffic_wrapper(
60
70
  structlogger.debug(
61
71
  "model_runner.bot_connection_established", deployment_id=deployment_id
62
72
  )
63
- socket_proxy_clients[sid] = client
73
+ socket_proxy_clients[sid] = SocketProxyClient(
74
+ user_id=user_info.get("sub", ""), socket=client
75
+ )
64
76
  return True
65
77
  else:
66
78
  structlogger.error(
@@ -87,12 +99,12 @@ def create_bridge_server(sio: AsyncServer, running_bots: Dict[str, BotSession])
87
99
  """Disconnect the bot connection."""
88
100
  structlogger.debug("model_runner.bot_disconnect", sid=sid)
89
101
  if sid in socket_proxy_clients:
90
- await socket_proxy_clients[sid].disconnect()
102
+ await socket_proxy_clients[sid].socket.disconnect()
91
103
  del socket_proxy_clients[sid]
92
104
 
93
105
  @sio.on("*")
94
106
  async def handle_message(event: str, sid: str, data: Dict[str, Any]) -> None:
95
- """ "Bridge messages between user and bot.
107
+ """Bridge messages between user and bot.
96
108
 
97
109
  Both incoming user messages to the bot_url and
98
110
  bot responses sent back to the client need to
@@ -103,7 +115,12 @@ def create_bridge_server(sio: AsyncServer, running_bots: Dict[str, BotSession])
103
115
  structlogger.error("model_runner.bot_not_connected", sid=sid)
104
116
  return
105
117
 
106
- await client.emit(event, data)
118
+ if "metadata" in data:
119
+ data.metadata["x-forwarded-for"] = client.user_id
120
+ else:
121
+ data["metadata"] = {"x-forwarded-for": client.user_id}
122
+
123
+ await client.socket.emit(event, data)
107
124
 
108
125
 
109
126
  async def create_bridge_client(
@@ -111,7 +128,7 @@ async def create_bridge_client(
111
128
  ) -> AsyncClient:
112
129
  """Create a new socket bridge client.
113
130
 
114
- Forwards messages comming from the bot to the user.
131
+ Forwards messages coming from the bot to the user.
115
132
  """
116
133
  client = AsyncClient()
117
134
 
@@ -129,6 +146,11 @@ async def create_bridge_client(
129
146
  structlogger.debug("model_runner.bot_message", deployment_id=deployment_id)
130
147
  await sio.emit("bot_message", data, room=sid)
131
148
 
149
+ @client.event # type: ignore[misc]
150
+ async def tracker(data: Dict[str, Any]) -> None:
151
+ structlogger.debug("model_runner.tracker_message", deployment_id=deployment_id)
152
+ await sio.emit("tracker", json.loads(data), room=sid)
153
+
132
154
  @client.event # type: ignore[misc]
133
155
  async def disconnect() -> None:
134
156
  structlogger.debug(
rasa/model_training.py CHANGED
@@ -23,6 +23,7 @@ from rasa.engine.storage.local_model_storage import LocalModelStorage
23
23
  from rasa.engine.storage.storage import ModelStorage
24
24
  from rasa.engine.training.components import FingerprintStatus
25
25
  from rasa.engine.training.graph_trainer import GraphTrainer
26
+ from rasa.shared.constants import CONFIG_RECIPE_KEY
26
27
  from rasa.shared.core.domain import Domain
27
28
  from rasa.shared.core.events import SlotSet
28
29
  from rasa.shared.core.training_data.structures import StoryGraph
@@ -304,7 +305,7 @@ async def _train_graph(
304
305
  is_finetuning = model_to_finetune is not None
305
306
 
306
307
  config = file_importer.get_config()
307
- recipe = Recipe.recipe_for_name(config.get("recipe"))
308
+ recipe = Recipe.recipe_for_name(config.get(CONFIG_RECIPE_KEY))
308
309
  config, _missing_keys, _configured_keys = recipe.auto_configure(
309
310
  file_importer.get_config_file_for_auto_config(),
310
311
  config,
rasa/server.py CHANGED
@@ -62,11 +62,9 @@ from rasa.shared.constants import (
62
62
  DOCS_BASE_URL,
63
63
  DOCS_URL_TRAINING_DATA,
64
64
  TEST_STORIES_FILE_PREFIX,
65
- DOCS_URL_FLOWS,
66
65
  )
67
66
  from rasa.shared.core.domain import Domain, InvalidDomain
68
67
  from rasa.shared.core.events import Event
69
- from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader
70
68
  from rasa.shared.core.trackers import (
71
69
  DialogueStateTracker,
72
70
  EventVerbosity,
@@ -74,7 +72,6 @@ from rasa.shared.core.trackers import (
74
72
  from rasa.shared.core.training_data.story_writer.yaml_story_writer import (
75
73
  YAMLStoryWriter,
76
74
  )
77
- from rasa.shared.exceptions import YamlException, RasaException
78
75
  from rasa.shared.importers.importer import TrainingDataImporter
79
76
  from rasa.shared.nlu.training_data.formats import RasaYAMLReader
80
77
  from rasa.shared.utils.schemas.events import EVENTS_SCHEMA
@@ -1569,8 +1566,7 @@ def _nlu_training_payload_from_json(
1569
1566
  )
1570
1567
 
1571
1568
 
1572
- def _validate_nlu_training_data_payload(yaml_text: str) -> None:
1573
- """Validate the NLU training data payload of the request body."""
1569
+ def _validate_yaml_training_payload(yaml_text: Text) -> None:
1574
1570
  try:
1575
1571
  RasaYAMLReader().validate(yaml_text)
1576
1572
  except Exception as e:
@@ -1582,38 +1578,6 @@ def _validate_nlu_training_data_payload(yaml_text: str) -> None:
1582
1578
  )
1583
1579
 
1584
1580
 
1585
- def _validate_flows_payload(yaml_text: str) -> None:
1586
- """Validate the flows payload of the request body."""
1587
- try:
1588
- YAMLFlowsReader().read_from_string(yaml_text)
1589
- except (YamlException, RasaException) as exc:
1590
- # if the payload does not contain any flows, we can ignore the error
1591
- if (
1592
- hasattr(exc, "validation_errors")
1593
- and exc.validation_errors is not None
1594
- and any(
1595
- [
1596
- "'flows' is a required property" in error.message
1597
- for error in exc.validation_errors
1598
- ]
1599
- )
1600
- ):
1601
- return None
1602
-
1603
- raise ErrorResponse(
1604
- HTTPStatus.BAD_REQUEST,
1605
- "BadRequest",
1606
- f"The request body does not contain valid YAML. Error: {exc}",
1607
- help_url=DOCS_URL_FLOWS,
1608
- )
1609
-
1610
-
1611
- def _validate_yaml_training_payload(yaml_text: str) -> None:
1612
- """Validate the YAML training payload of the request body."""
1613
- _validate_nlu_training_data_payload(yaml_text)
1614
- _validate_flows_payload(yaml_text)
1615
-
1616
-
1617
1581
  def _extract_core_additional_arguments(request: Request) -> Dict[Text, Any]:
1618
1582
  return {
1619
1583
  "augmentation_factor": rasa.utils.endpoints.int_arg(request, "augmentation", 50)
rasa/shared/constants.py CHANGED
@@ -19,7 +19,6 @@ DOCS_URL_GRAPH_COMPONENTS = DOCS_URL_CONCEPTS + "/components/custom-graph-compon
19
19
  DOCS_URL_GRAPH_RECIPE = DOCS_URL_CONCEPTS + "/components/graph-recipe"
20
20
  DOCS_URL_CATEGORICAL_SLOTS = DOCS_URL_CONCEPTS + "/domain#categorical-slot"
21
21
  DOCS_URL_DOMAIN = DOCS_URL_CONCEPTS + "/domain"
22
- DOCS_URL_FLOWS = DOCS_URL_CONCEPTS + "/flows"
23
22
 
24
23
  # Docs URLs for NLU-based assistants
25
24
  DOCS_URL_TRAINING_DATA = DOCS_URL_NLU_BASED + "/training-data-format"
@@ -102,16 +101,28 @@ ASSISTANT_ID_KEY = "assistant_id"
102
101
  ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
103
102
 
104
103
  CONFIG_MANDATORY_COMMON_KEYS = [ASSISTANT_ID_KEY]
105
- CONFIG_AUTOCONFIGURABLE_KEYS_CORE = ["policies"]
106
- CONFIG_AUTOCONFIGURABLE_KEYS_NLU = ["pipeline"]
104
+ CONFIG_NAME_KEY = "name"
105
+ CONFIG_POLICIES_KEY = "policies"
106
+ CONFIG_PIPELINE_KEY = "pipeline"
107
+ CONFIG_LANGUAGE_KEY = "language"
108
+ CONFIG_RECIPE_KEY = "recipe"
109
+ CONFIG_LLM_KEY = "llm"
110
+ CONFIG_MODEL_NAME_KEY = "model_name"
111
+ CONFIG_TRAIN_SCHEMA = "train_schema"
112
+ CONFIG_PREDICT_SCHEMA = "predict_schema"
113
+ CONFIG_AUTOCONFIGURABLE_KEYS_CORE = [CONFIG_POLICIES_KEY]
114
+ CONFIG_AUTOCONFIGURABLE_KEYS_NLU = [CONFIG_PIPELINE_KEY]
107
115
  CONFIG_AUTOCONFIGURABLE_KEYS = (
108
116
  CONFIG_AUTOCONFIGURABLE_KEYS_CORE + CONFIG_AUTOCONFIGURABLE_KEYS_NLU
109
117
  )
110
- CONFIG_KEYS_CORE = ["policies"] + CONFIG_MANDATORY_COMMON_KEYS
111
- CONFIG_KEYS_NLU = ["language", "pipeline"] + CONFIG_MANDATORY_COMMON_KEYS
118
+ CONFIG_KEYS_CORE = [CONFIG_POLICIES_KEY] + CONFIG_MANDATORY_COMMON_KEYS
119
+ CONFIG_KEYS_NLU = [
120
+ CONFIG_LANGUAGE_KEY,
121
+ CONFIG_PIPELINE_KEY,
122
+ ] + CONFIG_MANDATORY_COMMON_KEYS
112
123
  CONFIG_KEYS = CONFIG_KEYS_CORE + CONFIG_KEYS_NLU
113
124
  CONFIG_MANDATORY_KEYS_CORE: List[Text] = [] + CONFIG_MANDATORY_COMMON_KEYS
114
- CONFIG_MANDATORY_KEYS_NLU = ["language"] + CONFIG_MANDATORY_COMMON_KEYS
125
+ CONFIG_MANDATORY_KEYS_NLU = [CONFIG_LANGUAGE_KEY] + CONFIG_MANDATORY_COMMON_KEYS
115
126
  CONFIG_MANDATORY_KEYS = CONFIG_MANDATORY_KEYS_CORE + CONFIG_MANDATORY_KEYS_NLU
116
127
 
117
128
  # Keys related to Forms (in the Domain)
@@ -2,6 +2,10 @@ TEXT = "text"
2
2
  TEXT_TOKENS = "text_tokens"
3
3
  INTENT = "intent"
4
4
  COMMANDS = "commands"
5
+ PREDICTED_COMMANDS = "predicted_commands"
6
+ PROMPTS = "prompts"
7
+ KEY_USER_PROMPT = "user_prompt"
8
+ KEY_SYSTEM_PROMPT = "system_prompt"
5
9
  LLM_COMMANDS = "llm_commands" # needed for fine-tuning
6
10
  LLM_PROMPT = "llm_prompt" # needed for fine-tuning
7
11
  FLOWS_FROM_SEMANTIC_SEARCH = "flows_from_semantic_search"