rasa-pro 3.13.0a1.dev6__py3-none-any.whl → 3.13.0a1.dev7__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 (47) hide show
  1. rasa/builder/README.md +120 -0
  2. rasa/builder/config.py +69 -0
  3. rasa/builder/create_openai_vector_store.py +204 -45
  4. rasa/builder/exceptions.py +49 -0
  5. rasa/builder/llm_service.py +327 -0
  6. rasa/builder/logging_utils.py +51 -0
  7. rasa/builder/main.py +61 -0
  8. rasa/builder/models.py +174 -0
  9. rasa/builder/project_generator.py +264 -0
  10. rasa/builder/service.py +447 -0
  11. rasa/builder/skill_to_bot_prompt.jinja2 +6 -1
  12. rasa/builder/training_service.py +123 -0
  13. rasa/builder/validation_service.py +79 -0
  14. rasa/cli/project_templates/finance/config.yml +17 -0
  15. rasa/cli/project_templates/finance/credentials.yml +33 -0
  16. rasa/cli/project_templates/finance/data/flows/transfer_money.yml +5 -0
  17. rasa/cli/project_templates/finance/data/patterns/pattern_session_start.yml +7 -0
  18. rasa/cli/project_templates/finance/domain.yml +7 -0
  19. rasa/cli/project_templates/finance/endpoints.yml +58 -0
  20. rasa/cli/project_templates/plain/config.yml +17 -0
  21. rasa/cli/project_templates/plain/credentials.yml +33 -0
  22. rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +7 -0
  23. rasa/cli/project_templates/plain/domain.yml +5 -0
  24. rasa/cli/project_templates/plain/endpoints.yml +58 -0
  25. rasa/cli/project_templates/telecom/config.yml +17 -0
  26. rasa/cli/project_templates/telecom/credentials.yml +33 -0
  27. rasa/cli/project_templates/telecom/data/flows/upgrade_contract.yml +5 -0
  28. rasa/cli/project_templates/telecom/data/patterns/pattern_session_start.yml +7 -0
  29. rasa/cli/project_templates/telecom/domain.yml +7 -0
  30. rasa/cli/project_templates/telecom/endpoints.yml +58 -0
  31. rasa/cli/scaffold.py +19 -3
  32. rasa/core/actions/action.py +5 -3
  33. rasa/model_manager/model_api.py +1 -1
  34. rasa/model_manager/runner_service.py +1 -1
  35. rasa/model_manager/trainer_service.py +1 -1
  36. rasa/model_manager/utils.py +1 -29
  37. rasa/shared/core/domain.py +62 -15
  38. rasa/shared/core/flows/yaml_flows_io.py +16 -8
  39. rasa/telemetry.py +2 -1
  40. rasa/utils/io.py +27 -9
  41. rasa/version.py +1 -1
  42. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/METADATA +1 -1
  43. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/RECORD +46 -19
  44. rasa/builder/prompt_to_bot.py +0 -650
  45. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/NOTICE +0 -0
  46. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/WHEEL +0 -0
  47. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,33 @@
1
+ # This file contains the credentials for the voice & chat platforms
2
+ # which your bot is using.
3
+ # https://rasa.com/docs/rasa-pro/connectors/messaging-and-voice-channels/
4
+
5
+ rest:
6
+ # # you don't need to provide anything here - this channel doesn't
7
+ # # require any credentials
8
+
9
+
10
+ #facebook:
11
+ # verify: "<verify>"
12
+ # secret: "<your secret>"
13
+ # page-access-token: "<your page access token>"
14
+
15
+ #slack:
16
+ # slack_token: "<your slack token>"
17
+ # slack_channel: "<the slack channel>"
18
+ # slack_signing_secret: "<your slack signing secret>"
19
+
20
+ #socketio:
21
+ # user_message_evt: <event name for user message>
22
+ # bot_message_evt: <event name for bot messages>
23
+ # session_persistence: <true/false>
24
+
25
+ #mattermost:
26
+ # url: "https://<mattermost instance>/api/v4"
27
+ # token: "<bot token>"
28
+ # webhook_url: "<callback URL>"
29
+
30
+ # This entry is needed if you are using Rasa Enterprise. The entry represents credentials
31
+ # for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers.
32
+ rasa:
33
+ url: "http://localhost:5002/api"
@@ -0,0 +1,5 @@
1
+ flows:
2
+ transfer_money:
3
+ description: Transfer money between accounts.
4
+ steps:
5
+ - action: utter_transfer_money
@@ -0,0 +1,7 @@
1
+ flows:
2
+ pattern_session_start:
3
+ description: Custom session start to greet the user.
4
+ nlu_trigger:
5
+ - intent: session_start
6
+ steps:
7
+ - action: utter_greet
@@ -0,0 +1,7 @@
1
+ version: "3.1"
2
+
3
+ responses:
4
+ utter_greet:
5
+ - text: "Hello! Welcome to your finance assistant. How can I help you today?"
6
+ utter_transfer_money:
7
+ - text: "I'm sorry, I can't transfer money between accounts."
@@ -0,0 +1,58 @@
1
+ # This file contains the different endpoints your bot can use.
2
+
3
+ # Server where the models are pulled from.
4
+ # https://rasa.com/docs/rasa-pro/production/model-storage#fetching-models-from-a-server
5
+
6
+ #models:
7
+ # url: http://my-server.com/models/default_core@latest
8
+ # wait_time_between_pulls: 10 # [optional](default: 100)
9
+
10
+ # Server which runs your custom actions.
11
+ # https://rasa.com/docs/rasa-pro/concepts/custom-actions
12
+
13
+ action_endpoint:
14
+ actions_module: "actions"
15
+
16
+ # Tracker store which is used to store the conversations.
17
+ # By default the conversations are stored in memory.
18
+ # https://rasa.com/docs/rasa-pro/production/tracker-stores
19
+
20
+ #tracker_store:
21
+ # type: redis
22
+ # url: <host of the redis instance, e.g. localhost>
23
+ # port: <port of your redis instance, usually 6379>
24
+ # db: <number of your database within redis, e.g. 0>
25
+ # password: <password used for authentication>
26
+ # use_ssl: <whether or not the communication is encrypted, default false>
27
+
28
+ #tracker_store:
29
+ # type: mongod
30
+ # url: <url to your mongo instance, e.g. mongodb://localhost:27017>
31
+ # db: <name of the db within your mongo instance, e.g. rasa>
32
+ # username: <username used for authentication>
33
+ # password: <password used for authentication>
34
+
35
+ # Event broker which all conversation events should be streamed to.
36
+ # https://rasa.com/docs/rasa-pro/production/event-brokers
37
+
38
+ #event_broker:
39
+ # url: localhost
40
+ # username: username
41
+ # password: password
42
+ # queue: queue
43
+
44
+ # The lines below activate contextual rephrasing, using the default OpenAI language model.
45
+ # Ensure the OPENAI_API_KEY is set to prevent any missing API key errors.
46
+ # For more details, refer to the documentation:
47
+ # https://rasa.com/docs/rasa-pro/concepts/contextual-response-rephraser
48
+ # To enable the rephraser, remove the comment symbols in the lines below.
49
+ #nlg:
50
+ # type: rephrase
51
+
52
+ model_groups:
53
+ - id: openai-gpt-4o
54
+ models:
55
+ - provider: openai
56
+ model: gpt-4o-2024-11-20
57
+ request_timeout: 7
58
+ max_tokens: 256
@@ -0,0 +1,17 @@
1
+ # The config recipe.
2
+ recipe: default.v1
3
+
4
+ # The assistant project unique identifier
5
+ # This default value must be replaced with a unique assistant name within your deployment
6
+ assistant_id: placeholder_default
7
+
8
+ language: en
9
+ pipeline:
10
+ - name: CompactLLMCommandGenerator
11
+ llm:
12
+ model_group: openai-gpt-4o
13
+
14
+ # Configuration for Rasa Core.
15
+ policies:
16
+ - name: FlowPolicy
17
+ - name: IntentlessPolicy
@@ -0,0 +1,33 @@
1
+ # This file contains the credentials for the voice & chat platforms
2
+ # which your bot is using.
3
+ # https://rasa.com/docs/rasa-pro/connectors/messaging-and-voice-channels/
4
+
5
+ rest:
6
+ # # you don't need to provide anything here - this channel doesn't
7
+ # # require any credentials
8
+
9
+
10
+ #facebook:
11
+ # verify: "<verify>"
12
+ # secret: "<your secret>"
13
+ # page-access-token: "<your page access token>"
14
+
15
+ #slack:
16
+ # slack_token: "<your slack token>"
17
+ # slack_channel: "<the slack channel>"
18
+ # slack_signing_secret: "<your slack signing secret>"
19
+
20
+ #socketio:
21
+ # user_message_evt: <event name for user message>
22
+ # bot_message_evt: <event name for bot messages>
23
+ # session_persistence: <true/false>
24
+
25
+ #mattermost:
26
+ # url: "https://<mattermost instance>/api/v4"
27
+ # token: "<bot token>"
28
+ # webhook_url: "<callback URL>"
29
+
30
+ # This entry is needed if you are using Rasa Enterprise. The entry represents credentials
31
+ # for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers.
32
+ rasa:
33
+ url: "http://localhost:5002/api"
@@ -0,0 +1,7 @@
1
+ flows:
2
+ pattern_session_start:
3
+ description: Custom session start to greet the user.
4
+ nlu_trigger:
5
+ - intent: session_start
6
+ steps:
7
+ - action: utter_greet
@@ -0,0 +1,5 @@
1
+ version: "3.1"
2
+
3
+ responses:
4
+ utter_greet:
5
+ - text: "Hello! Welcome to your finance assistant. How can I help you today?"
@@ -0,0 +1,58 @@
1
+ # This file contains the different endpoints your bot can use.
2
+
3
+ # Server where the models are pulled from.
4
+ # https://rasa.com/docs/rasa-pro/production/model-storage#fetching-models-from-a-server
5
+
6
+ #models:
7
+ # url: http://my-server.com/models/default_core@latest
8
+ # wait_time_between_pulls: 10 # [optional](default: 100)
9
+
10
+ # Server which runs your custom actions.
11
+ # https://rasa.com/docs/rasa-pro/concepts/custom-actions
12
+
13
+ action_endpoint:
14
+ actions_module: "actions"
15
+
16
+ # Tracker store which is used to store the conversations.
17
+ # By default the conversations are stored in memory.
18
+ # https://rasa.com/docs/rasa-pro/production/tracker-stores
19
+
20
+ #tracker_store:
21
+ # type: redis
22
+ # url: <host of the redis instance, e.g. localhost>
23
+ # port: <port of your redis instance, usually 6379>
24
+ # db: <number of your database within redis, e.g. 0>
25
+ # password: <password used for authentication>
26
+ # use_ssl: <whether or not the communication is encrypted, default false>
27
+
28
+ #tracker_store:
29
+ # type: mongod
30
+ # url: <url to your mongo instance, e.g. mongodb://localhost:27017>
31
+ # db: <name of the db within your mongo instance, e.g. rasa>
32
+ # username: <username used for authentication>
33
+ # password: <password used for authentication>
34
+
35
+ # Event broker which all conversation events should be streamed to.
36
+ # https://rasa.com/docs/rasa-pro/production/event-brokers
37
+
38
+ #event_broker:
39
+ # url: localhost
40
+ # username: username
41
+ # password: password
42
+ # queue: queue
43
+
44
+ # The lines below activate contextual rephrasing, using the default OpenAI language model.
45
+ # Ensure the OPENAI_API_KEY is set to prevent any missing API key errors.
46
+ # For more details, refer to the documentation:
47
+ # https://rasa.com/docs/rasa-pro/concepts/contextual-response-rephraser
48
+ # To enable the rephraser, remove the comment symbols in the lines below.
49
+ #nlg:
50
+ # type: rephrase
51
+
52
+ model_groups:
53
+ - id: openai-gpt-4o
54
+ models:
55
+ - provider: openai
56
+ model: gpt-4o-2024-11-20
57
+ request_timeout: 7
58
+ max_tokens: 256
@@ -0,0 +1,17 @@
1
+ # The config recipe.
2
+ recipe: default.v1
3
+
4
+ # The assistant project unique identifier
5
+ # This default value must be replaced with a unique assistant name within your deployment
6
+ assistant_id: placeholder_default
7
+
8
+ language: en
9
+ pipeline:
10
+ - name: CompactLLMCommandGenerator
11
+ llm:
12
+ model_group: openai-gpt-4o
13
+
14
+ # Configuration for Rasa Core.
15
+ policies:
16
+ - name: FlowPolicy
17
+ - name: IntentlessPolicy
@@ -0,0 +1,33 @@
1
+ # This file contains the credentials for the voice & chat platforms
2
+ # which your bot is using.
3
+ # https://rasa.com/docs/rasa-pro/connectors/messaging-and-voice-channels/
4
+
5
+ rest:
6
+ # # you don't need to provide anything here - this channel doesn't
7
+ # # require any credentials
8
+
9
+
10
+ #facebook:
11
+ # verify: "<verify>"
12
+ # secret: "<your secret>"
13
+ # page-access-token: "<your page access token>"
14
+
15
+ #slack:
16
+ # slack_token: "<your slack token>"
17
+ # slack_channel: "<the slack channel>"
18
+ # slack_signing_secret: "<your slack signing secret>"
19
+
20
+ #socketio:
21
+ # user_message_evt: <event name for user message>
22
+ # bot_message_evt: <event name for bot messages>
23
+ # session_persistence: <true/false>
24
+
25
+ #mattermost:
26
+ # url: "https://<mattermost instance>/api/v4"
27
+ # token: "<bot token>"
28
+ # webhook_url: "<callback URL>"
29
+
30
+ # This entry is needed if you are using Rasa Enterprise. The entry represents credentials
31
+ # for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers.
32
+ rasa:
33
+ url: "http://localhost:5002/api"
@@ -0,0 +1,5 @@
1
+ flows:
2
+ upgrade_contract:
3
+ description: Upgrade contract.
4
+ steps:
5
+ - action: utter_upgrade_contract
@@ -0,0 +1,7 @@
1
+ flows:
2
+ pattern_session_start:
3
+ description: Custom session start to greet the user.
4
+ nlu_trigger:
5
+ - intent: session_start
6
+ steps:
7
+ - action: utter_greet
@@ -0,0 +1,7 @@
1
+ version: "3.1"
2
+
3
+ responses:
4
+ utter_greet:
5
+ - text: "Hello! Welcome to your telecom assistant. How can I help you today?"
6
+ utter_upgrade_contract:
7
+ - text: "I'm sorry, I can't upgrade your contract."
@@ -0,0 +1,58 @@
1
+ # This file contains the different endpoints your bot can use.
2
+
3
+ # Server where the models are pulled from.
4
+ # https://rasa.com/docs/rasa-pro/production/model-storage#fetching-models-from-a-server
5
+
6
+ #models:
7
+ # url: http://my-server.com/models/default_core@latest
8
+ # wait_time_between_pulls: 10 # [optional](default: 100)
9
+
10
+ # Server which runs your custom actions.
11
+ # https://rasa.com/docs/rasa-pro/concepts/custom-actions
12
+
13
+ action_endpoint:
14
+ actions_module: "actions"
15
+
16
+ # Tracker store which is used to store the conversations.
17
+ # By default the conversations are stored in memory.
18
+ # https://rasa.com/docs/rasa-pro/production/tracker-stores
19
+
20
+ #tracker_store:
21
+ # type: redis
22
+ # url: <host of the redis instance, e.g. localhost>
23
+ # port: <port of your redis instance, usually 6379>
24
+ # db: <number of your database within redis, e.g. 0>
25
+ # password: <password used for authentication>
26
+ # use_ssl: <whether or not the communication is encrypted, default false>
27
+
28
+ #tracker_store:
29
+ # type: mongod
30
+ # url: <url to your mongo instance, e.g. mongodb://localhost:27017>
31
+ # db: <name of the db within your mongo instance, e.g. rasa>
32
+ # username: <username used for authentication>
33
+ # password: <password used for authentication>
34
+
35
+ # Event broker which all conversation events should be streamed to.
36
+ # https://rasa.com/docs/rasa-pro/production/event-brokers
37
+
38
+ #event_broker:
39
+ # url: localhost
40
+ # username: username
41
+ # password: password
42
+ # queue: queue
43
+
44
+ # The lines below activate contextual rephrasing, using the default OpenAI language model.
45
+ # Ensure the OPENAI_API_KEY is set to prevent any missing API key errors.
46
+ # For more details, refer to the documentation:
47
+ # https://rasa.com/docs/rasa-pro/concepts/contextual-response-rephraser
48
+ # To enable the rephraser, remove the comment symbols in the lines below.
49
+ #nlg:
50
+ # type: rephrase
51
+
52
+ model_groups:
53
+ - id: openai-gpt-4o
54
+ models:
55
+ - provider: openai
56
+ model: gpt-4o-2024-11-20
57
+ request_timeout: 7
58
+ max_tokens: 256
rasa/cli/scaffold.py CHANGED
@@ -24,10 +24,21 @@ class ProjectTemplateName(Enum):
24
24
 
25
25
  DEFAULT = "default"
26
26
  TUTORIAL = "tutorial"
27
+ PLAIN = "plain"
28
+ FINANCE = "finance"
29
+ TELECOM = "telecom"
27
30
 
28
31
  def __str__(self) -> str:
29
32
  return self.value
30
33
 
34
+ @classmethod
35
+ def get_all_values(cls) -> List[str]:
36
+ return [name.value for name in cls]
37
+
38
+ @classmethod
39
+ def supported_values(cls) -> str:
40
+ return ", ".join(cls.get_all_values())
41
+
31
42
 
32
43
  template_domain_path = defaultdict(lambda: DEFAULT_DOMAIN_PATH)
33
44
  template_domain_path[ProjectTemplateName.DEFAULT] = "domain"
@@ -159,9 +170,14 @@ def create_initial_project(
159
170
  path: Text, template: ProjectTemplateName = ProjectTemplateName.DEFAULT
160
171
  ) -> None:
161
172
  """Creates directory structure and templates for initial project."""
162
- from distutils.dir_util import copy_tree
163
-
164
- copy_tree(scaffold_path(template), path)
173
+ import distutils.dir_util as dir_util
174
+
175
+ # clear the cache of the copy_tree function, this avoids issues if
176
+ # a project directory existed before and we removed folders in it
177
+ # with shutil.rmtree. see
178
+ # https://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree
179
+ dir_util._path_created.clear()
180
+ dir_util.copy_tree(scaffold_path(template), path)
165
181
 
166
182
 
167
183
  def scaffold_path(template: ProjectTemplateName) -> Text:
@@ -908,10 +908,12 @@ class RemoteAction(Action):
908
908
  draft.setdefault("buttons", [])
909
909
  draft["buttons"].extend(buttons)
910
910
 
911
- # Avoid overwriting `draft` values with empty values
912
911
  response = {k: v for k, v in response.items() if v}
913
- draft.update(response)
914
- bot_messages.append(create_bot_utterance(draft, tracker.current_language))
912
+
913
+ response.update(draft)
914
+ bot_messages.append(
915
+ create_bot_utterance(response, tracker.current_language)
916
+ )
915
917
 
916
918
  return bot_messages
917
919
 
@@ -43,7 +43,6 @@ from rasa.model_manager.utils import (
43
43
  get_logs_content,
44
44
  logs_base_path,
45
45
  models_base_path,
46
- subpath,
47
46
  )
48
47
  from rasa.model_manager.warm_rasa_process import (
49
48
  initialize_warm_rasa_process,
@@ -53,6 +52,7 @@ from rasa.server import ErrorResponse
53
52
  from rasa.shared.exceptions import InvalidConfigException
54
53
  from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string
55
54
  from rasa.studio.upload import build_calm_import_parts
55
+ from rasa.utils.io import subpath
56
56
 
57
57
  dotenv.load_dotenv()
58
58
 
@@ -14,10 +14,10 @@ from rasa.model_manager import config
14
14
  from rasa.model_manager.utils import (
15
15
  logs_path,
16
16
  models_base_path,
17
- subpath,
18
17
  write_encoded_data_to_file,
19
18
  )
20
19
  from rasa.model_manager.warm_rasa_process import start_rasa_process
20
+ from rasa.utils.io import subpath
21
21
 
22
22
  structlogger = structlog.get_logger()
23
23
 
@@ -13,13 +13,13 @@ from rasa.model_manager.utils import (
13
13
  ensure_base_directory_exists,
14
14
  logs_path,
15
15
  models_base_path,
16
- subpath,
17
16
  write_encoded_data_to_file,
18
17
  )
19
18
  from rasa.model_manager.warm_rasa_process import (
20
19
  start_rasa_process,
21
20
  )
22
21
  from rasa.model_training import generate_random_model_name
22
+ from rasa.utils.io import subpath
23
23
 
24
24
  structlogger = structlog.get_logger()
25
25
 
@@ -5,15 +5,11 @@ from typing import Optional
5
5
  import structlog
6
6
 
7
7
  from rasa.model_manager import config
8
- from rasa.shared.exceptions import RasaException
8
+ from rasa.utils.io import subpath
9
9
 
10
10
  structlogger = structlog.get_logger()
11
11
 
12
12
 
13
- class InvalidPathException(RasaException):
14
- """Raised if a path is invalid - e.g. path traversal is detected."""
15
-
16
-
17
13
  def write_encoded_data_to_file(encoded_data: bytes, file: str) -> None:
18
14
  """Write base64 encoded data to a file."""
19
15
  # create the directory if it does not exist of the parent directory
@@ -53,30 +49,6 @@ def logs_path(action_id: str) -> str:
53
49
  return subpath(logs_base_path(), f"{action_id}.txt")
54
50
 
55
51
 
56
- def subpath(parent: str, child: str) -> str:
57
- """Return the path to the child directory of the parent directory.
58
-
59
- Ensures, that child doesn't navigate to parent directories. Prevents
60
- path traversal. Raises an InvalidPathException if the path is invalid.
61
-
62
- Based on Snyk's directory traversal mitigation:
63
- https://learn.snyk.io/lesson/directory-traversal/
64
- """
65
- safe_path = os.path.abspath(os.path.join(parent, child))
66
- parent = os.path.abspath(parent)
67
-
68
- common_base = os.path.commonpath([parent, safe_path])
69
- if common_base != parent:
70
- raise InvalidPathException(f"Invalid path: {safe_path}")
71
-
72
- if os.path.basename(safe_path) != child:
73
- raise InvalidPathException(
74
- f"Invalid path - path traversal detected: {safe_path}"
75
- )
76
-
77
- return safe_path
78
-
79
-
80
52
  def get_logs_content(action_id: str) -> Optional[str]:
81
53
  """Return the content of the log file for a given action id."""
82
54
  try:
@@ -98,6 +98,8 @@ IS_RETRIEVAL_INTENT_KEY = "is_retrieval_intent"
98
98
  ENTITY_ROLES_KEY = "roles"
99
99
  ENTITY_GROUPS_KEY = "groups"
100
100
  ENTITY_FEATURIZATION_KEY = "influence_conversation"
101
+ STORE_ENTITIES_AS_SLOTS_KEY = "store_entities_as_slots"
102
+ DOMAIN_CONFIG_KEY = "config"
101
103
 
102
104
  KEY_SLOTS = "slots"
103
105
  KEY_INTENTS = "intents"
@@ -146,6 +148,8 @@ MERGE_FUNC_MAPPING: Dict[Text, Callable[..., Any]] = {
146
148
  KEY_FORMS: rasa.shared.utils.common.merge_dicts,
147
149
  }
148
150
 
151
+ DEFAULT_STORE_ENTITIES_AS_SLOTS = True
152
+
149
153
  DICT_DATA_KEYS = [
150
154
  key
151
155
  for key, value in MERGE_FUNC_MAPPING.items()
@@ -318,7 +322,7 @@ class Domain:
318
322
  actions = cls._collect_action_names(domain_actions)
319
323
 
320
324
  additional_arguments = {
321
- **data.get("config", {}),
325
+ **data.get(DOMAIN_CONFIG_KEY, {}),
322
326
  "actions_which_explicitly_need_domain": (
323
327
  cls._collect_actions_which_explicitly_need_domain(domain_actions)
324
328
  ),
@@ -468,9 +472,9 @@ class Domain:
468
472
  return domain_dict
469
473
 
470
474
  if override:
471
- config = domain_dict.get("config", {})
475
+ config = domain_dict.get(DOMAIN_CONFIG_KEY, {})
472
476
  for key, val in config.items():
473
- combined["config"][key] = val
477
+ combined[DOMAIN_CONFIG_KEY][key] = val
474
478
 
475
479
  if (
476
480
  override
@@ -508,10 +512,10 @@ class Domain:
508
512
  return combined
509
513
 
510
514
  def partial_merge(self, other: Domain) -> Domain:
511
- """
512
- Returns a new Domain with intersection-based merging:
513
- - For each domain section only overwrite items that already exist in self.
514
- - Brand-new items in `other` are ignored.
515
+ """Returns a new Domain with intersection-based merging.
516
+
517
+ For each domain section only overwrite items that already exist in self.
518
+ Brand-new items in `other` are ignored.
515
519
 
516
520
  Args:
517
521
  other: The domain to merge with.
@@ -543,9 +547,9 @@ class Domain:
543
547
  return Domain.from_dict(updated_self)
544
548
 
545
549
  def difference(self, other: Domain) -> Domain:
546
- """
547
- Returns a new Domain containing items in `self` that are NOT in `other`,
548
- using simple equality checks for dict/list items.
550
+ """Returns a new Domain containing items in `self` that are NOT in `other`.
551
+
552
+ Uses simple equality checks for dict/list items.
549
553
 
550
554
  Args:
551
555
  other: The domain to compare with.
@@ -598,9 +602,16 @@ class Domain:
598
602
  ) -> Dict:
599
603
  # add the config, session_config and training data version defaults
600
604
  # if not included in the original domain dict
601
- if "config" not in data and not store_entities_as_slots:
605
+ if (
606
+ DOMAIN_CONFIG_KEY not in data
607
+ and store_entities_as_slots != DEFAULT_STORE_ENTITIES_AS_SLOTS
608
+ ):
602
609
  data.update(
603
- {"config": {"store_entities_as_slots": store_entities_as_slots}}
610
+ {
611
+ DOMAIN_CONFIG_KEY: {
612
+ STORE_ENTITIES_AS_SLOTS_KEY: store_entities_as_slots
613
+ }
614
+ }
604
615
  )
605
616
 
606
617
  if SESSION_CONFIG_KEY not in data:
@@ -937,7 +948,7 @@ class Domain:
937
948
  forms: Union[Dict[Text, Any], List[Text]],
938
949
  data: Dict,
939
950
  action_texts: Optional[List[Text]] = None,
940
- store_entities_as_slots: bool = True,
951
+ store_entities_as_slots: bool = DEFAULT_STORE_ENTITIES_AS_SLOTS,
941
952
  session_config: SessionConfig = SessionConfig.default(),
942
953
  **kwargs: Any,
943
954
  ) -> None:
@@ -1711,9 +1722,45 @@ class Domain:
1711
1722
  else:
1712
1723
  return True
1713
1724
 
1714
- def as_dict(self) -> Dict[Text, Any]:
1725
+ def _uses_custom_session_config(self) -> bool:
1726
+ """Check if the domain uses a custom session config."""
1727
+ return self._data.get(SESSION_CONFIG_KEY) != SessionConfig.default().as_dict()
1728
+
1729
+ def _uses_custom_domain_config(self) -> bool:
1730
+ """Check if the domain uses a custom domain config."""
1731
+ return self._data.get(DOMAIN_CONFIG_KEY) != {
1732
+ STORE_ENTITIES_AS_SLOTS_KEY: DEFAULT_STORE_ENTITIES_AS_SLOTS
1733
+ }
1734
+
1735
+ def _cleaned_json_data(self) -> Dict[Text, Any]:
1736
+ """Remove default values from the domain data.
1737
+
1738
+ Only retains data that was customized by the user.
1739
+
1740
+ Returns:
1741
+ A cleaned dictionary version of the domain.
1742
+ """
1743
+ cleaned_data = copy.deepcopy(self._data)
1744
+
1745
+ # Remove default config if it only contains store_entities_as_slots: False
1746
+ if DOMAIN_CONFIG_KEY in cleaned_data and not self._uses_custom_domain_config():
1747
+ del cleaned_data[DOMAIN_CONFIG_KEY]
1748
+
1749
+ # Remove default session config if it matches the default values
1750
+ if (
1751
+ SESSION_CONFIG_KEY in cleaned_data
1752
+ and not self._uses_custom_session_config()
1753
+ ):
1754
+ del cleaned_data[SESSION_CONFIG_KEY]
1755
+
1756
+ return cleaned_data
1757
+
1758
+ def as_dict(self, should_clean_json: bool = False) -> Dict[Text, Any]:
1715
1759
  """Return serialized `Domain`."""
1716
- return self._data
1760
+ if should_clean_json:
1761
+ return self._cleaned_json_data()
1762
+ else:
1763
+ return self._data
1717
1764
 
1718
1765
  @staticmethod
1719
1766
  def get_responses_with_multilines(