rasa-pro 3.12.0.dev13__py3-none-any.whl → 3.12.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/anonymization/anonymization_rule_executor.py +16 -10
- rasa/cli/data.py +16 -0
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/utils.py +12 -0
- rasa/core/actions/action.py +84 -191
- rasa/core/actions/action_run_slot_rejections.py +16 -4
- rasa/core/channels/__init__.py +2 -0
- rasa/core/channels/studio_chat.py +19 -0
- rasa/core/channels/telegram.py +42 -24
- rasa/core/channels/voice_ready/utils.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +10 -4
- rasa/core/channels/voice_stream/asr/azure.py +14 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +20 -4
- rasa/core/channels/voice_stream/audiocodes.py +264 -0
- rasa/core/channels/voice_stream/browser_audio.py +4 -1
- rasa/core/channels/voice_stream/call_state.py +3 -0
- rasa/core/channels/voice_stream/genesys.py +6 -2
- rasa/core/channels/voice_stream/tts/azure.py +9 -1
- rasa/core/channels/voice_stream/tts/cartesia.py +14 -8
- rasa/core/channels/voice_stream/voice_channel.py +23 -2
- rasa/core/constants.py +2 -0
- rasa/core/nlg/contextual_response_rephraser.py +18 -1
- rasa/core/nlg/generator.py +83 -15
- rasa/core/nlg/response.py +6 -3
- rasa/core/nlg/translate.py +55 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flows/flow_executor.py +12 -5
- rasa/core/processor.py +72 -9
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +24 -6
- rasa/dialogue_understanding/commands/change_flow_command.py +20 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/clarify_command.py +29 -3
- rasa/dialogue_understanding/commands/command.py +1 -16
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +20 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +20 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +24 -2
- rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +20 -2
- rasa/dialogue_understanding/commands/utils.py +98 -4
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_parser.py +15 -12
- rasa/dialogue_understanding/generator/constants.py +3 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -5
- rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +16 -2
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +2 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +77 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_default.jinja2 +68 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +84 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +460 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -310
- rasa/dialogue_understanding/patterns/collect_information.py +1 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +16 -0
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +39 -0
- rasa/dialogue_understanding_test/du_test_case.py +28 -8
- rasa/dialogue_understanding_test/du_test_result.py +13 -9
- rasa/dialogue_understanding_test/io.py +14 -0
- rasa/e2e_test/utils/io.py +0 -37
- rasa/engine/graph.py +1 -0
- rasa/engine/language.py +140 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_recipe.py +2 -0
- rasa/engine/recipes/graph_recipe.py +2 -0
- rasa/engine/storage/local_model_storage.py +1 -0
- rasa/engine/storage/storage.py +4 -1
- rasa/model_manager/runner_service.py +7 -4
- rasa/model_manager/socket_bridge.py +7 -6
- rasa/shared/constants.py +15 -13
- rasa/shared/core/constants.py +2 -0
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +83 -19
- rasa/shared/core/flows/flows_yaml_schema.json +31 -3
- rasa/shared/core/flows/steps/collect.py +1 -36
- rasa/shared/core/flows/utils.py +28 -4
- rasa/shared/core/flows/validation.py +1 -1
- rasa/shared/core/slot_mappings.py +208 -5
- rasa/shared/core/slots.py +131 -1
- rasa/shared/core/trackers.py +74 -1
- rasa/shared/importers/importer.py +50 -2
- rasa/shared/nlu/training_data/schemas/responses.yml +19 -12
- rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +138 -3
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +3 -1
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +3 -1
- rasa/shared/providers/_configs/litellm_router_client_config.py +3 -1
- rasa/shared/providers/_configs/model_group_config.py +4 -2
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +3 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +3 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +3 -1
- rasa/shared/providers/constants.py +6 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +28 -3
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +3 -1
- rasa/shared/providers/llm/_base_litellm_client.py +42 -17
- rasa/shared/providers/llm/azure_openai_llm_client.py +81 -25
- rasa/shared/providers/llm/default_litellm_llm_client.py +3 -1
- rasa/shared/providers/llm/litellm_router_llm_client.py +29 -8
- rasa/shared/providers/llm/llm_client.py +23 -7
- rasa/shared/providers/llm/openai_llm_client.py +9 -3
- rasa/shared/providers/llm/rasa_llm_client.py +11 -2
- rasa/shared/providers/llm/self_hosted_llm_client.py +30 -11
- rasa/shared/providers/router/_base_litellm_router_client.py +3 -1
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/llm.py +30 -7
- rasa/shared/utils/pykwalify_extensions.py +24 -0
- rasa/shared/utils/schemas/domain.yml +26 -0
- rasa/telemetry.py +2 -1
- rasa/tracing/config.py +2 -0
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/instrumentation.py +36 -0
- rasa/tracing/instrumentation/metrics.py +41 -0
- rasa/tracing/metric_instrument_provider.py +40 -0
- rasa/validator.py +372 -7
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/METADATA +2 -1
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/RECORD +128 -113
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc1.dist-info}/entry_points.txt +0 -0
rasa/shared/core/slots.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
from abc import ABC, abstractmethod
|
|
5
|
+
from dataclasses import dataclass
|
|
3
6
|
from typing import Any, Dict, List, Optional, Text, Type
|
|
4
7
|
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
5
10
|
import rasa.shared.core.constants
|
|
6
11
|
import rasa.shared.utils.common
|
|
7
12
|
import rasa.shared.utils.io
|
|
@@ -9,6 +14,9 @@ from rasa.shared.constants import (
|
|
|
9
14
|
DOCS_URL_CATEGORICAL_SLOTS,
|
|
10
15
|
DOCS_URL_NLU_BASED_SLOTS,
|
|
11
16
|
DOCS_URL_SLOTS,
|
|
17
|
+
REFILL_UTTER,
|
|
18
|
+
REJECTIONS,
|
|
19
|
+
UTTER_ASK_PREFIX,
|
|
12
20
|
)
|
|
13
21
|
from rasa.shared.exceptions import RasaException
|
|
14
22
|
|
|
@@ -23,6 +31,80 @@ class InvalidSlotConfigError(RasaException, ValueError):
|
|
|
23
31
|
"""Raised if a slot's config is invalid."""
|
|
24
32
|
|
|
25
33
|
|
|
34
|
+
@dataclass
|
|
35
|
+
class SlotRejection:
|
|
36
|
+
"""A pair of validation condition and an utterance for the case of failure."""
|
|
37
|
+
|
|
38
|
+
if_: str
|
|
39
|
+
"""The condition that should be checked."""
|
|
40
|
+
utter: str
|
|
41
|
+
"""The utterance that should be executed if the condition is met."""
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def from_dict(data: Dict[str, Any]) -> SlotRejection:
|
|
45
|
+
"""Create a SlotRejection object from serialized data.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
data: data for a SlotRejection object in a serialized format
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
A SlotRejection object
|
|
52
|
+
"""
|
|
53
|
+
return SlotRejection(
|
|
54
|
+
if_=data["if"],
|
|
55
|
+
utter=data["utter"],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
59
|
+
"""Serialize the SlotRejection object.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
the SlotRejection object as serialized data
|
|
63
|
+
"""
|
|
64
|
+
return {
|
|
65
|
+
"if": self.if_,
|
|
66
|
+
"utter": self.utter,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class SlotValidation(BaseModel):
|
|
71
|
+
rejections: List[SlotRejection] = Field(alias=REJECTIONS)
|
|
72
|
+
"""how the slot value is validated using predicate evaluation."""
|
|
73
|
+
refill_utter: str = Field(alias=REFILL_UTTER)
|
|
74
|
+
"""The utterance that the assistant uses to ask for the slot."""
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def from_dict(data: Dict[str, Any]) -> SlotValidation:
|
|
78
|
+
"""Creates a SlotValidation object from serialised data.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
data: data for a SlotValidation object in a serialized format
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
A SlotValidation object
|
|
85
|
+
"""
|
|
86
|
+
rejections = data.get(REJECTIONS)
|
|
87
|
+
if rejections is not None:
|
|
88
|
+
rejections = [
|
|
89
|
+
SlotRejection.from_dict(rejection) for rejection in rejections
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
return SlotValidation(
|
|
93
|
+
rejections=rejections, refill_utter=data.get(REFILL_UTTER)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
97
|
+
"""Serialize the SlotValidation object.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
the SlotValidation object as serialized data
|
|
101
|
+
"""
|
|
102
|
+
return {
|
|
103
|
+
REJECTIONS: [rejection.as_dict() for rejection in self.rejections],
|
|
104
|
+
REFILL_UTTER: self.refill_utter,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
26
108
|
class Slot(ABC):
|
|
27
109
|
"""Key-value store for storing information during a conversation."""
|
|
28
110
|
|
|
@@ -42,6 +124,7 @@ class Slot(ABC):
|
|
|
42
124
|
is_builtin: bool = False,
|
|
43
125
|
shared_for_coexistence: bool = False,
|
|
44
126
|
filled_by: Optional[str] = None,
|
|
127
|
+
validation: Optional[Dict[str, Any]] = None,
|
|
45
128
|
) -> None:
|
|
46
129
|
"""Create a Slot.
|
|
47
130
|
|
|
@@ -59,6 +142,8 @@ class Slot(ABC):
|
|
|
59
142
|
shared_for_coexistence: If `True` the slot is not forgotten after either
|
|
60
143
|
dm1 or CALM finishes.
|
|
61
144
|
filled_by: The name of the extractor that fills the slot.
|
|
145
|
+
validation: The validation rules that should be used to validate
|
|
146
|
+
slot values.
|
|
62
147
|
"""
|
|
63
148
|
from rasa.shared.core.slot_mappings import SlotMapping
|
|
64
149
|
|
|
@@ -73,6 +158,12 @@ class Slot(ABC):
|
|
|
73
158
|
self.shared_for_coexistence = shared_for_coexistence
|
|
74
159
|
self._filled_by = filled_by
|
|
75
160
|
|
|
161
|
+
if validation:
|
|
162
|
+
validation.setdefault(REFILL_UTTER, f"{UTTER_ASK_PREFIX}{self.name}")
|
|
163
|
+
self.validation = (
|
|
164
|
+
SlotValidation.from_dict(validation) if validation else validation
|
|
165
|
+
)
|
|
166
|
+
|
|
76
167
|
def feature_dimensionality(self) -> int:
|
|
77
168
|
"""How many features this single slot creates.
|
|
78
169
|
|
|
@@ -191,12 +282,15 @@ class Slot(ABC):
|
|
|
191
282
|
|
|
192
283
|
def persistence_info(self) -> Dict[str, Any]:
|
|
193
284
|
"""Returns relevant information to persist this slot."""
|
|
194
|
-
|
|
285
|
+
persistence_info_dict = {
|
|
195
286
|
"type": rasa.shared.utils.common.module_path_from_instance(self),
|
|
196
287
|
"initial_value": self.initial_value,
|
|
197
288
|
"influence_conversation": self.influence_conversation,
|
|
198
289
|
"mappings": [mapping.as_dict() for mapping in self.mappings],
|
|
199
290
|
}
|
|
291
|
+
if self.validation:
|
|
292
|
+
persistence_info_dict["validation"] = self.validation.as_dict() # type: ignore
|
|
293
|
+
return persistence_info_dict
|
|
200
294
|
|
|
201
295
|
def fingerprint(self) -> Text:
|
|
202
296
|
"""Returns a unique hash for the slot which is stable across python runs.
|
|
@@ -213,6 +307,10 @@ class Slot(ABC):
|
|
|
213
307
|
return False
|
|
214
308
|
return self.name == other.name and self.value == other.value
|
|
215
309
|
|
|
310
|
+
def requires_validation(self) -> bool:
|
|
311
|
+
"""Indicates if the slot requires validation."""
|
|
312
|
+
return True if self.validation else False
|
|
313
|
+
|
|
216
314
|
|
|
217
315
|
class FloatSlot(Slot):
|
|
218
316
|
"""A slot storing a float value."""
|
|
@@ -673,3 +771,35 @@ class AnySlot(Slot):
|
|
|
673
771
|
f"implement a custom slot type by subclassing '{Slot.__name__}'. "
|
|
674
772
|
f"See the documentation for more information: {DOCS_URL_NLU_BASED_SLOTS}"
|
|
675
773
|
)
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
class StrictCategoricalSlot(CategoricalSlot):
|
|
777
|
+
"""A categorical slot that strictly enforces allowed values."""
|
|
778
|
+
|
|
779
|
+
type_name = "strict_categorical"
|
|
780
|
+
|
|
781
|
+
def coerce_value(self, value: Any) -> Any:
|
|
782
|
+
"""Coerce the value to one of the allowed ones or raise an error if invalid."""
|
|
783
|
+
if value is None:
|
|
784
|
+
return value
|
|
785
|
+
|
|
786
|
+
for allowed_value in self.values:
|
|
787
|
+
# Allowed values are always stored as strings, so we can use casefold().
|
|
788
|
+
if value.casefold() == allowed_value.casefold():
|
|
789
|
+
return allowed_value
|
|
790
|
+
|
|
791
|
+
raise InvalidSlotConfigError(
|
|
792
|
+
f"Value '{value}' is not allowed for the slot '{self.name}'. "
|
|
793
|
+
f"Allowed values are: {self.values}"
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
@Slot.value.setter # type: ignore[attr-defined,misc]
|
|
797
|
+
def value(self, value: Any) -> None:
|
|
798
|
+
"""Set the slot's value using strict coercion."""
|
|
799
|
+
coerced_value = self.coerce_value(value)
|
|
800
|
+
super(StrictCategoricalSlot, self.__class__).value.fset(self, coerced_value)
|
|
801
|
+
|
|
802
|
+
def add_default_value(self) -> None:
|
|
803
|
+
# StrictCategoricalSlot enforces validation against a specified set of values,
|
|
804
|
+
# so default values should not be automatically added.
|
|
805
|
+
pass
|
rasa/shared/core/trackers.py
CHANGED
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
import time
|
|
7
7
|
from collections import deque
|
|
8
8
|
from enum import Enum
|
|
9
|
+
from functools import cached_property
|
|
9
10
|
from typing import (
|
|
10
11
|
TYPE_CHECKING,
|
|
11
12
|
Any,
|
|
@@ -26,6 +27,7 @@ from typing import (
|
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
import rasa.shared.utils.io
|
|
30
|
+
from rasa.engine.language import Language
|
|
29
31
|
from rasa.shared.constants import (
|
|
30
32
|
ASSISTANT_ID_KEY,
|
|
31
33
|
DEFAULT_SENDER_ID,
|
|
@@ -37,6 +39,7 @@ from rasa.shared.core.constants import (
|
|
|
37
39
|
ACTION_SESSION_START_NAME,
|
|
38
40
|
ACTIVE_LOOP,
|
|
39
41
|
FOLLOWUP_ACTION,
|
|
42
|
+
LANGUAGE_SLOT,
|
|
40
43
|
LOOP_NAME,
|
|
41
44
|
PREVIOUS_ACTION,
|
|
42
45
|
SHOULD_NOT_BE_SET,
|
|
@@ -61,7 +64,8 @@ from rasa.shared.core.events import (
|
|
|
61
64
|
UserUttered,
|
|
62
65
|
)
|
|
63
66
|
from rasa.shared.core.flows import FlowsList
|
|
64
|
-
from rasa.shared.core.slots import AnySlot, Slot
|
|
67
|
+
from rasa.shared.core.slots import AnySlot, Slot, StrictCategoricalSlot
|
|
68
|
+
from rasa.shared.exceptions import RasaException
|
|
65
69
|
from rasa.shared.nlu.constants import (
|
|
66
70
|
ACTION_NAME,
|
|
67
71
|
ACTION_TEXT,
|
|
@@ -1097,6 +1101,75 @@ class DialogueStateTracker:
|
|
|
1097
1101
|
|
|
1098
1102
|
return FlowsList(active_flows)
|
|
1099
1103
|
|
|
1104
|
+
@cached_property
|
|
1105
|
+
def supported_languages(self) -> List[Language]:
|
|
1106
|
+
"""Returns the supported languages for this model configuration
|
|
1107
|
+
|
|
1108
|
+
Returns:
|
|
1109
|
+
A list of supported languages.
|
|
1110
|
+
"""
|
|
1111
|
+
if LANGUAGE_SLOT not in self.slots:
|
|
1112
|
+
raise RasaException(
|
|
1113
|
+
f"The required slot '{LANGUAGE_SLOT}' is missing from the tracker. "
|
|
1114
|
+
f"Please ensure that a slot named '{LANGUAGE_SLOT}' exists."
|
|
1115
|
+
)
|
|
1116
|
+
|
|
1117
|
+
language_slot = self.slots[LANGUAGE_SLOT]
|
|
1118
|
+
|
|
1119
|
+
if not isinstance(language_slot, StrictCategoricalSlot):
|
|
1120
|
+
raise RasaException(
|
|
1121
|
+
f"The slot '{LANGUAGE_SLOT}' must be of type "
|
|
1122
|
+
f"'{StrictCategoricalSlot.type_name}'. "
|
|
1123
|
+
f"Please update the slot configuration accordingly."
|
|
1124
|
+
)
|
|
1125
|
+
|
|
1126
|
+
return [
|
|
1127
|
+
Language.from_language_code(language_code)
|
|
1128
|
+
for language_code in language_slot.values
|
|
1129
|
+
]
|
|
1130
|
+
|
|
1131
|
+
@property
|
|
1132
|
+
def current_language(self) -> Optional[Language]:
|
|
1133
|
+
"""Get the language of the current conversation.
|
|
1134
|
+
|
|
1135
|
+
Returns:
|
|
1136
|
+
The language of the current conversation or `None` if not set.
|
|
1137
|
+
"""
|
|
1138
|
+
language_code = self.get_slot("language")
|
|
1139
|
+
if not language_code:
|
|
1140
|
+
return None
|
|
1141
|
+
|
|
1142
|
+
supported_languages = self.supported_languages or []
|
|
1143
|
+
matching_language = (
|
|
1144
|
+
language
|
|
1145
|
+
for language in supported_languages
|
|
1146
|
+
if language.code == language_code
|
|
1147
|
+
)
|
|
1148
|
+
return next(matching_language, None)
|
|
1149
|
+
|
|
1150
|
+
@property
|
|
1151
|
+
def default_language(self) -> Language:
|
|
1152
|
+
"""Get the assistant's default language.
|
|
1153
|
+
|
|
1154
|
+
Returns:
|
|
1155
|
+
The assistant's default language.
|
|
1156
|
+
|
|
1157
|
+
Raises:
|
|
1158
|
+
RasaException: If no default language is defined in the config.
|
|
1159
|
+
"""
|
|
1160
|
+
supported_languages = self.supported_languages or []
|
|
1161
|
+
matching_language = (
|
|
1162
|
+
language for language in supported_languages if language.is_default is True
|
|
1163
|
+
)
|
|
1164
|
+
try:
|
|
1165
|
+
return next(matching_language)
|
|
1166
|
+
except StopIteration:
|
|
1167
|
+
raise RasaException(
|
|
1168
|
+
"No default language configured. "
|
|
1169
|
+
"Please configure the `language` parameter in config.yml file. "
|
|
1170
|
+
"Example: `language: en`."
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1100
1173
|
|
|
1101
1174
|
class TrackerEventDiffEngine:
|
|
1102
1175
|
"""Computes event difference of two trackers."""
|
|
@@ -20,16 +20,19 @@ import rasa.shared.constants
|
|
|
20
20
|
import rasa.shared.core.constants
|
|
21
21
|
import rasa.shared.utils.common
|
|
22
22
|
import rasa.shared.utils.io
|
|
23
|
+
from rasa.shared.constants import CONFIG_ADDITIONAL_LANGUAGES_KEY, CONFIG_LANGUAGE_KEY
|
|
23
24
|
from rasa.shared.core.domain import (
|
|
24
25
|
IS_RETRIEVAL_INTENT_KEY,
|
|
25
26
|
KEY_ACTIONS,
|
|
26
27
|
KEY_E2E_ACTIONS,
|
|
27
28
|
KEY_INTENTS,
|
|
28
29
|
KEY_RESPONSES,
|
|
30
|
+
KEY_SLOTS,
|
|
29
31
|
Domain,
|
|
30
32
|
)
|
|
31
33
|
from rasa.shared.core.events import ActionExecuted, UserUttered
|
|
32
34
|
from rasa.shared.core.flows import FlowsList
|
|
35
|
+
from rasa.shared.core.slots import StrictCategoricalSlot
|
|
33
36
|
from rasa.shared.core.training_data.structures import StoryGraph
|
|
34
37
|
from rasa.shared.nlu.constants import ACTION_NAME, ENTITIES
|
|
35
38
|
from rasa.shared.nlu.training_data.message import Message
|
|
@@ -202,8 +205,10 @@ class TrainingDataImporter(ABC):
|
|
|
202
205
|
)
|
|
203
206
|
]
|
|
204
207
|
|
|
205
|
-
return
|
|
206
|
-
|
|
208
|
+
return LanguageImporter(
|
|
209
|
+
E2EImporter(
|
|
210
|
+
FlowSyncImporter(ResponsesSyncImporter(CombinedDataImporter(importers)))
|
|
211
|
+
)
|
|
207
212
|
)
|
|
208
213
|
|
|
209
214
|
@staticmethod
|
|
@@ -522,6 +527,49 @@ class FlowSyncImporter(PassThroughImporter):
|
|
|
522
527
|
return self._importer.get_domain()
|
|
523
528
|
|
|
524
529
|
|
|
530
|
+
class LanguageImporter(PassThroughImporter):
|
|
531
|
+
"""Importer that configures the language settings in the domain."""
|
|
532
|
+
|
|
533
|
+
@cached_method
|
|
534
|
+
def get_domain(self) -> Domain:
|
|
535
|
+
domain = self._importer.get_domain()
|
|
536
|
+
if domain.is_empty():
|
|
537
|
+
return domain
|
|
538
|
+
|
|
539
|
+
config = self._importer.get_config()
|
|
540
|
+
language = config.get(CONFIG_LANGUAGE_KEY)
|
|
541
|
+
additional_languages = config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY) or []
|
|
542
|
+
|
|
543
|
+
values = additional_languages.copy()
|
|
544
|
+
if language and language not in values:
|
|
545
|
+
values.append(language)
|
|
546
|
+
|
|
547
|
+
# Prepare the serialized representation of the language slot
|
|
548
|
+
slot_name = rasa.shared.core.constants.LANGUAGE_SLOT
|
|
549
|
+
serialized_slot: Dict[Text, Any] = {
|
|
550
|
+
"type": StrictCategoricalSlot.type_name,
|
|
551
|
+
"initial_value": language,
|
|
552
|
+
"values": values,
|
|
553
|
+
"mappings": [],
|
|
554
|
+
"is_builtin": True,
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
domain_with_language_slot = Domain.from_dict(
|
|
558
|
+
{KEY_SLOTS: {slot_name: serialized_slot}}
|
|
559
|
+
)
|
|
560
|
+
return domain.merge(domain_with_language_slot)
|
|
561
|
+
|
|
562
|
+
@cached_method
|
|
563
|
+
def get_user_domain(self) -> Domain:
|
|
564
|
+
"""Delegate to the underlying importer to get the user domain."""
|
|
565
|
+
return self._importer.get_user_domain()
|
|
566
|
+
|
|
567
|
+
@cached_method
|
|
568
|
+
def get_user_flows(self) -> FlowsList:
|
|
569
|
+
"""Delegate to the underlying importer to get user flows."""
|
|
570
|
+
return self._importer.get_user_flows()
|
|
571
|
+
|
|
572
|
+
|
|
525
573
|
class ResponsesSyncImporter(PassThroughImporter):
|
|
526
574
|
"""Importer that syncs `responses` between Domain and NLU training data.
|
|
527
575
|
|
|
@@ -17,6 +17,12 @@ schema;responses:
|
|
|
17
17
|
required: False
|
|
18
18
|
text:
|
|
19
19
|
type: "str"
|
|
20
|
+
translation:
|
|
21
|
+
type: "map"
|
|
22
|
+
allowempty: True
|
|
23
|
+
mapping:
|
|
24
|
+
regex;(.*):
|
|
25
|
+
type: "str"
|
|
20
26
|
image:
|
|
21
27
|
type: "str"
|
|
22
28
|
custom:
|
|
@@ -32,6 +38,18 @@ schema;responses:
|
|
|
32
38
|
type: "str"
|
|
33
39
|
payload:
|
|
34
40
|
type: "str"
|
|
41
|
+
translation:
|
|
42
|
+
type: "map"
|
|
43
|
+
allowempty: True
|
|
44
|
+
mapping:
|
|
45
|
+
regex;(.*):
|
|
46
|
+
type: "map"
|
|
47
|
+
allowempty: True
|
|
48
|
+
mapping:
|
|
49
|
+
title:
|
|
50
|
+
type: "str"
|
|
51
|
+
payload:
|
|
52
|
+
type: "str"
|
|
35
53
|
button_type:
|
|
36
54
|
type: "str"
|
|
37
55
|
quick_replies:
|
|
@@ -57,15 +75,4 @@ schema;responses:
|
|
|
57
75
|
metadata:
|
|
58
76
|
type: "any"
|
|
59
77
|
condition:
|
|
60
|
-
type: "
|
|
61
|
-
sequence:
|
|
62
|
-
- type: "map"
|
|
63
|
-
allowempty: False
|
|
64
|
-
mapping:
|
|
65
|
-
type:
|
|
66
|
-
type: "str"
|
|
67
|
-
enum: ['slot']
|
|
68
|
-
name:
|
|
69
|
-
type: "str"
|
|
70
|
-
value:
|
|
71
|
-
type: "any"
|
|
78
|
+
type: "any"
|