rasa-pro 3.13.0.dev7__py3-none-any.whl → 3.13.0.dev8__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/__main__.py +0 -3
- rasa/api.py +1 -1
- rasa/cli/dialogue_understanding_test.py +1 -1
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +1 -1
- rasa/cli/export.py +1 -1
- rasa/cli/llm_fine_tuning.py +12 -11
- rasa/cli/project_templates/defaults.py +133 -0
- rasa/cli/run.py +1 -1
- rasa/cli/studio/link.py +53 -0
- rasa/cli/studio/pull.py +78 -0
- rasa/cli/studio/push.py +78 -0
- rasa/cli/studio/studio.py +12 -0
- rasa/cli/studio/upload.py +8 -0
- rasa/cli/train.py +1 -1
- rasa/cli/utils.py +1 -1
- rasa/cli/x.py +1 -1
- rasa/constants.py +2 -0
- rasa/core/__init__.py +0 -16
- rasa/core/actions/action.py +5 -1
- rasa/core/actions/action_repeat_bot_messages.py +18 -22
- rasa/core/actions/action_run_slot_rejections.py +0 -1
- rasa/core/agent.py +16 -1
- rasa/core/available_endpoints.py +146 -0
- rasa/core/brokers/pika.py +1 -2
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/channel.py +2 -2
- rasa/core/channels/hangouts.py +8 -5
- rasa/core/channels/mattermost.py +1 -1
- rasa/core/channels/rasa_chat.py +2 -4
- rasa/core/channels/rest.py +5 -4
- rasa/core/channels/studio_chat.py +3 -2
- rasa/core/channels/vier_cvg.py +1 -2
- rasa/core/channels/voice_ready/audiocodes.py +1 -8
- rasa/core/channels/voice_stream/audiocodes.py +7 -4
- rasa/core/channels/voice_stream/genesys.py +2 -2
- rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
- rasa/core/channels/voice_stream/voice_channel.py +33 -22
- rasa/core/http_interpreter.py +3 -7
- rasa/core/jobs.py +2 -1
- rasa/core/nlg/contextual_response_rephraser.py +34 -9
- rasa/core/nlg/generator.py +0 -1
- rasa/core/nlg/interpolator.py +2 -3
- rasa/core/nlg/summarize.py +39 -5
- rasa/core/policies/enterprise_search_policy.py +283 -62
- rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
- rasa/core/policies/flow_policy.py +1 -1
- rasa/core/policies/flows/flow_executor.py +96 -17
- rasa/core/policies/intentless_policy.py +9 -7
- rasa/core/processor.py +104 -51
- rasa/core/run.py +33 -11
- rasa/core/tracker_stores/tracker_store.py +1 -1
- rasa/core/training/interactive.py +1 -1
- rasa/core/utils.py +24 -97
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
- rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +2 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
- rasa/dialogue_understanding/commands/clarify_command.py +5 -1
- rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +4 -2
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +11 -1
- rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
- rasa/dialogue_understanding/commands/utils.py +26 -2
- rasa/dialogue_understanding/generator/__init__.py +7 -1
- rasa/dialogue_understanding/generator/command_generator.py +4 -2
- rasa/dialogue_understanding/generator/command_parser.py +2 -2
- rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +12 -33
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +26 -461
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +8 -58
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
- rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
- rasa/dialogue_understanding/processor/command_processor.py +3 -3
- rasa/dialogue_understanding/processor/command_processor_component.py +3 -3
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +17 -4
- rasa/dialogue_understanding/utils.py +68 -12
- rasa/dialogue_understanding_test/du_test_case.py +1 -1
- rasa/dialogue_understanding_test/du_test_runner.py +4 -22
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +2 -6
- rasa/e2e_test/e2e_test_runner.py +1 -1
- rasa/engine/constants.py +1 -1
- rasa/engine/recipes/default_recipe.py +26 -2
- rasa/engine/validation.py +3 -2
- rasa/hooks.py +0 -28
- rasa/llm_fine_tuning/annotation_module.py +39 -9
- rasa/llm_fine_tuning/conversations.py +3 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +66 -49
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +52 -44
- rasa/llm_fine_tuning/paraphrasing_module.py +10 -12
- rasa/llm_fine_tuning/storage.py +4 -4
- rasa/llm_fine_tuning/utils.py +63 -1
- rasa/model_manager/model_api.py +88 -0
- rasa/model_manager/trainer_service.py +4 -4
- rasa/plugin.py +1 -11
- rasa/privacy/__init__.py +0 -0
- rasa/privacy/constants.py +83 -0
- rasa/privacy/event_broker_utils.py +77 -0
- rasa/privacy/privacy_config.py +281 -0
- rasa/privacy/privacy_config_schema.json +86 -0
- rasa/privacy/privacy_filter.py +340 -0
- rasa/privacy/privacy_manager.py +576 -0
- rasa/server.py +23 -2
- rasa/shared/constants.py +3 -0
- rasa/shared/core/constants.py +4 -3
- rasa/shared/core/domain.py +7 -0
- rasa/shared/core/events.py +37 -7
- rasa/shared/core/flows/flow.py +1 -2
- rasa/shared/core/flows/flows_yaml_schema.json +3 -0
- rasa/shared/core/flows/steps/collect.py +46 -2
- rasa/shared/core/slots.py +28 -0
- rasa/shared/exceptions.py +4 -0
- rasa/shared/utils/llm.py +161 -6
- rasa/shared/utils/yaml.py +32 -0
- rasa/studio/data_handler.py +3 -3
- rasa/studio/download/download.py +37 -60
- rasa/studio/download/flows.py +23 -31
- rasa/studio/link.py +200 -0
- rasa/studio/pull.py +94 -0
- rasa/studio/push.py +131 -0
- rasa/studio/upload.py +117 -67
- rasa/telemetry.py +82 -25
- rasa/tracing/config.py +3 -4
- rasa/tracing/constants.py +19 -1
- rasa/tracing/instrumentation/attribute_extractors.py +10 -2
- rasa/tracing/instrumentation/instrumentation.py +53 -2
- rasa/tracing/instrumentation/metrics.py +98 -15
- rasa/tracing/metric_instrument_provider.py +75 -3
- rasa/utils/common.py +1 -27
- rasa/utils/log_utils.py +1 -45
- rasa/validator.py +2 -8
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev7.dist-info → rasa_pro-3.13.0.dev8.dist-info}/METADATA +5 -6
- {rasa_pro-3.13.0.dev7.dist-info → rasa_pro-3.13.0.dev8.dist-info}/RECORD +143 -129
- rasa/anonymization/__init__.py +0 -2
- rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
- rasa/anonymization/anonymization_pipeline.py +0 -286
- rasa/anonymization/anonymization_rule_executor.py +0 -266
- rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
- rasa/anonymization/schemas/config.yml +0 -47
- rasa/anonymization/utils.py +0 -118
- {rasa_pro-3.13.0.dev7.dist-info → rasa_pro-3.13.0.dev8.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev7.dist-info → rasa_pro-3.13.0.dev8.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev7.dist-info → rasa_pro-3.13.0.dev8.dist-info}/entry_points.txt +0 -0
rasa/core/agent.py
CHANGED
|
@@ -13,6 +13,7 @@ from aiohttp import ClientError
|
|
|
13
13
|
|
|
14
14
|
import rasa.shared.utils.io
|
|
15
15
|
from rasa.core import jobs
|
|
16
|
+
from rasa.core.available_endpoints import AvailableEndpoints
|
|
16
17
|
from rasa.core.channels.channel import OutputChannel, UserMessage
|
|
17
18
|
from rasa.core.constants import DEFAULT_REQUEST_TIMEOUT
|
|
18
19
|
from rasa.core.exceptions import AgentNotReady
|
|
@@ -27,13 +28,14 @@ from rasa.core.tracker_stores.tracker_store import (
|
|
|
27
28
|
InMemoryTrackerStore,
|
|
28
29
|
TrackerStore,
|
|
29
30
|
)
|
|
30
|
-
from rasa.core.utils import AvailableEndpoints
|
|
31
31
|
from rasa.exceptions import ModelNotFound
|
|
32
32
|
from rasa.nlu.utils import is_url
|
|
33
|
+
from rasa.privacy.privacy_manager import BackgroundPrivacyManager
|
|
33
34
|
from rasa.shared.constants import DEFAULT_SENDER_ID
|
|
34
35
|
from rasa.shared.core.domain import Domain
|
|
35
36
|
from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
|
|
36
37
|
from rasa.shared.exceptions import RasaException
|
|
38
|
+
from rasa.telemetry import track_privacy_enabled
|
|
37
39
|
from rasa.utils.common import TempDirectoryPath, get_temp_dir_name
|
|
38
40
|
from rasa.utils.endpoints import EndpointConfig
|
|
39
41
|
|
|
@@ -222,6 +224,7 @@ async def load_agent(
|
|
|
222
224
|
generator = None
|
|
223
225
|
action_endpoint = None
|
|
224
226
|
http_interpreter = None
|
|
227
|
+
privacy_manager = None
|
|
225
228
|
|
|
226
229
|
if endpoints:
|
|
227
230
|
broker = await EventBroker.create(endpoints.event_broker, loop=loop)
|
|
@@ -234,6 +237,12 @@ async def load_agent(
|
|
|
234
237
|
model_server = endpoints.model if endpoints.model else model_server
|
|
235
238
|
if endpoints.nlu:
|
|
236
239
|
http_interpreter = RasaNLUHttpInterpreter(endpoints.nlu)
|
|
240
|
+
if endpoints.privacy:
|
|
241
|
+
privacy_manager = await BackgroundPrivacyManager.create_instance(
|
|
242
|
+
endpoints=endpoints,
|
|
243
|
+
event_loop=loop,
|
|
244
|
+
)
|
|
245
|
+
track_privacy_enabled(privacy_manager.config, broker)
|
|
237
246
|
|
|
238
247
|
agent = Agent(
|
|
239
248
|
generator=generator,
|
|
@@ -244,6 +253,7 @@ async def load_agent(
|
|
|
244
253
|
remote_storage=remote_storage,
|
|
245
254
|
http_interpreter=http_interpreter,
|
|
246
255
|
endpoints=endpoints,
|
|
256
|
+
privacy_manager=privacy_manager,
|
|
247
257
|
)
|
|
248
258
|
|
|
249
259
|
try:
|
|
@@ -306,6 +316,7 @@ class Agent:
|
|
|
306
316
|
remote_storage: Optional[StorageType] = None,
|
|
307
317
|
http_interpreter: Optional[RasaNLUHttpInterpreter] = None,
|
|
308
318
|
endpoints: Optional[AvailableEndpoints] = None,
|
|
319
|
+
privacy_manager: Optional[BackgroundPrivacyManager] = None,
|
|
309
320
|
):
|
|
310
321
|
"""Initializes an `Agent`."""
|
|
311
322
|
self.domain = domain
|
|
@@ -321,6 +332,7 @@ class Agent:
|
|
|
321
332
|
self._set_fingerprint(fingerprint)
|
|
322
333
|
self.model_server = model_server
|
|
323
334
|
self.remote_storage = remote_storage
|
|
335
|
+
self.privacy_manager = privacy_manager
|
|
324
336
|
|
|
325
337
|
@classmethod
|
|
326
338
|
def load(
|
|
@@ -336,6 +348,7 @@ class Agent:
|
|
|
336
348
|
remote_storage: Optional[StorageType] = None,
|
|
337
349
|
http_interpreter: Optional[RasaNLUHttpInterpreter] = None,
|
|
338
350
|
endpoints: Optional[AvailableEndpoints] = None,
|
|
351
|
+
privacy_manager: Optional[BackgroundPrivacyManager] = None,
|
|
339
352
|
) -> Agent:
|
|
340
353
|
"""Constructs a new agent and loads the processor and model."""
|
|
341
354
|
agent = Agent(
|
|
@@ -349,6 +362,7 @@ class Agent:
|
|
|
349
362
|
remote_storage=remote_storage,
|
|
350
363
|
http_interpreter=http_interpreter,
|
|
351
364
|
endpoints=endpoints,
|
|
365
|
+
privacy_manager=privacy_manager,
|
|
352
366
|
)
|
|
353
367
|
agent.load_model(model_path=model_path, fingerprint=fingerprint)
|
|
354
368
|
return agent
|
|
@@ -365,6 +379,7 @@ class Agent:
|
|
|
365
379
|
generator=self.nlg,
|
|
366
380
|
http_interpreter=self.http_interpreter,
|
|
367
381
|
endpoints=self.endpoints,
|
|
382
|
+
privacy_manager=self.privacy_manager,
|
|
368
383
|
)
|
|
369
384
|
self.domain = self.processor.domain
|
|
370
385
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
from typing import Any, Dict, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from rasa.shared.constants import DEFAULT_ENDPOINTS_PATH
|
|
7
|
+
from rasa.shared.core.constants import (
|
|
8
|
+
GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE,
|
|
9
|
+
GLOBAL_SILENCE_TIMEOUT_KEY,
|
|
10
|
+
)
|
|
11
|
+
from rasa.shared.exceptions import RasaException
|
|
12
|
+
from rasa.utils.endpoints import (
|
|
13
|
+
EndpointConfig,
|
|
14
|
+
read_endpoint_config,
|
|
15
|
+
read_property_config_from_endpoints_file,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclasses.dataclass
|
|
20
|
+
class InteractionHandlingConfig:
|
|
21
|
+
"""Configuration for interaction handling."""
|
|
22
|
+
|
|
23
|
+
global_silence_timeout: Union[float, int] = GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE
|
|
24
|
+
|
|
25
|
+
def __post_init__(self) -> None:
|
|
26
|
+
# Validate the type of `global_silence_timeout`.
|
|
27
|
+
if isinstance(self.global_silence_timeout, str):
|
|
28
|
+
try:
|
|
29
|
+
self.global_silence_timeout = float(self.global_silence_timeout)
|
|
30
|
+
except ValueError:
|
|
31
|
+
raise RasaException(
|
|
32
|
+
f"Type for {GLOBAL_SILENCE_TIMEOUT_KEY} is wrong, expected number. "
|
|
33
|
+
f"Got: '{self.global_silence_timeout}'. "
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if not isinstance(self.global_silence_timeout, (float, int)):
|
|
37
|
+
raise RasaException(
|
|
38
|
+
f"Type for {GLOBAL_SILENCE_TIMEOUT_KEY} is wrong, expected number. "
|
|
39
|
+
f"Got: '{type(self.global_silence_timeout)}'. "
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if self.global_silence_timeout <= 0:
|
|
43
|
+
raise RasaException(
|
|
44
|
+
f"Value for {GLOBAL_SILENCE_TIMEOUT_KEY} must be a positive number. "
|
|
45
|
+
f"Got: '{self.global_silence_timeout}'. "
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def from_dict(cls, data: Optional[Dict[str, Any]]) -> InteractionHandlingConfig:
|
|
50
|
+
"""Create a InteractionHandlingConfig instance from a dictionary."""
|
|
51
|
+
return cls(
|
|
52
|
+
global_silence_timeout=data.get(
|
|
53
|
+
GLOBAL_SILENCE_TIMEOUT_KEY, GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE
|
|
54
|
+
)
|
|
55
|
+
if data is not None
|
|
56
|
+
else GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AvailableEndpoints:
|
|
61
|
+
"""Collection of configured endpoints."""
|
|
62
|
+
|
|
63
|
+
_instance = None
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def read_endpoints(cls, endpoint_file: str) -> AvailableEndpoints:
|
|
67
|
+
"""Read the different endpoints from a yaml file."""
|
|
68
|
+
nlg = read_endpoint_config(endpoint_file, endpoint_type="nlg")
|
|
69
|
+
nlu = read_endpoint_config(endpoint_file, endpoint_type="nlu")
|
|
70
|
+
action = read_endpoint_config(endpoint_file, endpoint_type="action_endpoint")
|
|
71
|
+
model = read_endpoint_config(endpoint_file, endpoint_type="models")
|
|
72
|
+
tracker_store = read_endpoint_config(
|
|
73
|
+
endpoint_file, endpoint_type="tracker_store"
|
|
74
|
+
)
|
|
75
|
+
lock_store = read_endpoint_config(endpoint_file, endpoint_type="lock_store")
|
|
76
|
+
event_broker = read_endpoint_config(endpoint_file, endpoint_type="event_broker")
|
|
77
|
+
vector_store = read_endpoint_config(endpoint_file, endpoint_type="vector_store")
|
|
78
|
+
model_groups = read_property_config_from_endpoints_file(
|
|
79
|
+
endpoint_file, property_name="model_groups"
|
|
80
|
+
)
|
|
81
|
+
privacy = read_property_config_from_endpoints_file(
|
|
82
|
+
endpoint_file, property_name="privacy"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
interaction_handling = InteractionHandlingConfig.from_dict(
|
|
86
|
+
read_property_config_from_endpoints_file(
|
|
87
|
+
endpoint_file, property_name="interaction_handling"
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return cls(
|
|
92
|
+
nlg,
|
|
93
|
+
nlu,
|
|
94
|
+
action,
|
|
95
|
+
model,
|
|
96
|
+
tracker_store,
|
|
97
|
+
lock_store,
|
|
98
|
+
event_broker,
|
|
99
|
+
vector_store,
|
|
100
|
+
model_groups,
|
|
101
|
+
privacy,
|
|
102
|
+
interaction_handling,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def __init__(
|
|
106
|
+
self,
|
|
107
|
+
nlg: Optional[EndpointConfig] = None,
|
|
108
|
+
nlu: Optional[EndpointConfig] = None,
|
|
109
|
+
action: Optional[EndpointConfig] = None,
|
|
110
|
+
model: Optional[EndpointConfig] = None,
|
|
111
|
+
tracker_store: Optional[EndpointConfig] = None,
|
|
112
|
+
lock_store: Optional[EndpointConfig] = None,
|
|
113
|
+
event_broker: Optional[EndpointConfig] = None,
|
|
114
|
+
vector_store: Optional[EndpointConfig] = None,
|
|
115
|
+
model_groups: Optional[List[Dict[str, Any]]] = None,
|
|
116
|
+
privacy: Optional[Dict[str, Any]] = None,
|
|
117
|
+
interaction_handling: InteractionHandlingConfig = InteractionHandlingConfig(
|
|
118
|
+
global_silence_timeout=GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE
|
|
119
|
+
),
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Create an `AvailableEndpoints` object."""
|
|
122
|
+
self.model = model
|
|
123
|
+
self.action = action
|
|
124
|
+
self.nlu = nlu
|
|
125
|
+
self.nlg = nlg
|
|
126
|
+
self.tracker_store = tracker_store
|
|
127
|
+
self.lock_store = lock_store
|
|
128
|
+
self.event_broker = event_broker
|
|
129
|
+
self.vector_store = vector_store
|
|
130
|
+
self.model_groups = model_groups
|
|
131
|
+
self.privacy = privacy
|
|
132
|
+
self.interaction_handling = interaction_handling
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def get_instance(
|
|
136
|
+
cls, endpoint_file: Optional[str] = DEFAULT_ENDPOINTS_PATH
|
|
137
|
+
) -> AvailableEndpoints:
|
|
138
|
+
"""Get the singleton instance of AvailableEndpoints."""
|
|
139
|
+
# Ensure that the instance is initialized only once.
|
|
140
|
+
if cls._instance is None:
|
|
141
|
+
cls._instance = cls.read_endpoints(endpoint_file)
|
|
142
|
+
return cls._instance
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def reset_instance(cls) -> None:
|
|
146
|
+
cls._instance = None
|
rasa/core/brokers/pika.py
CHANGED
|
@@ -316,9 +316,8 @@ class PikaEventBroker(EventBroker):
|
|
|
316
316
|
except Exception as e:
|
|
317
317
|
structlogger.error(
|
|
318
318
|
"pika.events.publish.failed",
|
|
319
|
-
event_info="
|
|
319
|
+
event_info=f"Failed to publish Pika event. Error: {e}",
|
|
320
320
|
host=self.host,
|
|
321
|
-
rasa_event=reduced_event,
|
|
322
321
|
)
|
|
323
322
|
if self.should_keep_unpublished_messages:
|
|
324
323
|
self._unpublished_events.append(event)
|
|
@@ -115,8 +115,8 @@ class BotFramework(OutputChannel):
|
|
|
115
115
|
|
|
116
116
|
if not send_response.ok:
|
|
117
117
|
logger.error(
|
|
118
|
-
"Error trying to send botframework messge.
|
|
119
|
-
send_response.
|
|
118
|
+
"Error trying to send botframework messge. "
|
|
119
|
+
f"Error: {send_response.reason}"
|
|
120
120
|
)
|
|
121
121
|
|
|
122
122
|
async def send_text_message(
|
rasa/core/channels/channel.py
CHANGED
|
@@ -103,7 +103,7 @@ class UserMessage:
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
def register(
|
|
106
|
-
input_channels: List[
|
|
106
|
+
input_channels: List[InputChannel], app: Sanic, route: Optional[Text]
|
|
107
107
|
) -> None:
|
|
108
108
|
"""Registers input channel blueprints with Sanic."""
|
|
109
109
|
|
|
@@ -129,7 +129,7 @@ class InputChannel:
|
|
|
129
129
|
return cls.__name__
|
|
130
130
|
|
|
131
131
|
@classmethod
|
|
132
|
-
def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) ->
|
|
132
|
+
def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> InputChannel:
|
|
133
133
|
return cls()
|
|
134
134
|
|
|
135
135
|
def url_prefix(self) -> Text:
|
rasa/core/channels/hangouts.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import copy
|
|
2
1
|
import logging
|
|
3
2
|
from asyncio import CancelledError
|
|
4
3
|
from typing import Any, Awaitable, Callable, Dict, Iterable, List, Optional, Text, Union
|
|
@@ -314,13 +313,17 @@ class HangoutsInput(InputChannel):
|
|
|
314
313
|
metadata={"room": room_name},
|
|
315
314
|
)
|
|
316
315
|
)
|
|
317
|
-
except CancelledError:
|
|
316
|
+
except CancelledError as e:
|
|
318
317
|
structlogger.error(
|
|
319
|
-
"hangouts.message.blueprint.timeout",
|
|
318
|
+
"hangouts.message.blueprint.timeout",
|
|
319
|
+
event_info=f"Message processing was cancelled. Error: {e}",
|
|
320
320
|
)
|
|
321
|
-
except Exception:
|
|
321
|
+
except Exception as e:
|
|
322
322
|
structlogger.exception(
|
|
323
|
-
"hangouts.message.blueprint.failure",
|
|
323
|
+
"hangouts.message.blueprint.failure",
|
|
324
|
+
event_info=(
|
|
325
|
+
f"An error occurred while processing the message. Error: {e}",
|
|
326
|
+
),
|
|
324
327
|
)
|
|
325
328
|
|
|
326
329
|
return response.json(collector.messages)
|
rasa/core/channels/mattermost.py
CHANGED
|
@@ -28,7 +28,7 @@ class MattermostBot(OutputChannel):
|
|
|
28
28
|
if r.status_code == 200:
|
|
29
29
|
return r.headers["Token"]
|
|
30
30
|
else:
|
|
31
|
-
logger.error(f"Failed to login mattermost user
|
|
31
|
+
logger.error(f"Failed to login mattermost user. Response: {r}")
|
|
32
32
|
return None
|
|
33
33
|
|
|
34
34
|
def __init__(
|
rasa/core/channels/rasa_chat.py
CHANGED
|
@@ -107,10 +107,8 @@ class RasaChatInput(RestInput):
|
|
|
107
107
|
return req.json[CONVERSATION_ID_KEY]
|
|
108
108
|
else:
|
|
109
109
|
logger.error(
|
|
110
|
-
"User
|
|
111
|
-
"conversation '{}'.".format(
|
|
112
|
-
jwt_payload[JWT_USERNAME_KEY], req.json[CONVERSATION_ID_KEY]
|
|
113
|
-
)
|
|
110
|
+
"User does not have permissions to send messages to "
|
|
111
|
+
"conversation '{}'.".format(req.json[CONVERSATION_ID_KEY])
|
|
114
112
|
)
|
|
115
113
|
raise SanicException(status_code=401)
|
|
116
114
|
|
rasa/core/channels/rest.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import copy
|
|
3
2
|
import inspect
|
|
4
3
|
import json
|
|
5
4
|
import logging
|
|
@@ -166,11 +165,13 @@ class RestInput(InputChannel):
|
|
|
166
165
|
)
|
|
167
166
|
except CancelledError:
|
|
168
167
|
structlogger.error(
|
|
169
|
-
"rest.message.received.timeout",
|
|
168
|
+
"rest.message.received.timeout",
|
|
169
|
+
event_info="Message processing was cancelled.",
|
|
170
170
|
)
|
|
171
|
-
except Exception:
|
|
171
|
+
except Exception as e:
|
|
172
172
|
structlogger.exception(
|
|
173
|
-
"rest.message.received.failure",
|
|
173
|
+
"rest.message.received.failure",
|
|
174
|
+
event_info=f"Message processing failed. Error: {e}",
|
|
174
175
|
)
|
|
175
176
|
|
|
176
177
|
return response.json(collector.messages)
|
|
@@ -83,7 +83,9 @@ class StudioTrackerUpdatePlugin:
|
|
|
83
83
|
|
|
84
84
|
def handle_tracker_update(self, tracker: "DialogueStateTracker") -> None:
|
|
85
85
|
"""Handles a tracker update when triggered by a hook."""
|
|
86
|
-
structlogger.info(
|
|
86
|
+
structlogger.info(
|
|
87
|
+
"studio_chat.after_tracker_update", sender_id=tracker.sender_id
|
|
88
|
+
)
|
|
87
89
|
# directly create a dump to avoid the tracker getting modified by another
|
|
88
90
|
# function before it gets published (since the publishing is scheduled
|
|
89
91
|
# as an async task)
|
|
@@ -185,7 +187,6 @@ class StudioChatInput(SocketIOInput):
|
|
|
185
187
|
output_channel = self.get_output_channel()
|
|
186
188
|
|
|
187
189
|
await processor._run_prediction_loop(output_channel, tracker)
|
|
188
|
-
await processor.run_anonymization_pipeline(tracker)
|
|
189
190
|
await self.agent.tracker_store.save(tracker)
|
|
190
191
|
|
|
191
192
|
await self.on_tracker_updated(tracker)
|
rasa/core/channels/vier_cvg.py
CHANGED
|
@@ -129,9 +129,8 @@ class CVGOutput(OutputChannel):
|
|
|
129
129
|
)
|
|
130
130
|
|
|
131
131
|
logger.info(
|
|
132
|
-
"Creating incoming UserMessage: {
|
|
132
|
+
"Creating incoming UserMessage: {output_channel=%s, sender_id=%s, metadata=%s}" # noqa: E501
|
|
133
133
|
% (
|
|
134
|
-
user_message.text,
|
|
135
134
|
user_message.output_channel,
|
|
136
135
|
user_message.sender_id,
|
|
137
136
|
user_message.metadata,
|
|
@@ -193,16 +193,9 @@ class Conversation:
|
|
|
193
193
|
try:
|
|
194
194
|
await on_new_message(user_msg)
|
|
195
195
|
except Exception as e: # skipcq: PYL-W0703
|
|
196
|
-
if isinstance(user_msg.text, dict):
|
|
197
|
-
anonymized_info = json.dumps(user_msg.text)
|
|
198
|
-
elif isinstance(user_msg.text, str):
|
|
199
|
-
anonymized_info = user_msg.text
|
|
200
|
-
else:
|
|
201
|
-
anonymized_info = INFO_UNKNOWN
|
|
202
|
-
|
|
203
196
|
structlogger.exception(
|
|
204
197
|
"audiocodes.handle.activities.failure",
|
|
205
|
-
|
|
198
|
+
sender_id=self.conversation_id,
|
|
206
199
|
error=e,
|
|
207
200
|
exc_info=True,
|
|
208
201
|
)
|
|
@@ -108,15 +108,19 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
|
|
|
108
108
|
server_url: str,
|
|
109
109
|
asr_config: Dict,
|
|
110
110
|
tts_config: Dict,
|
|
111
|
-
monitor_silence: bool = False,
|
|
112
111
|
):
|
|
113
112
|
mark_as_beta_feature("Audiocodes (audiocodes_stream) Channel")
|
|
114
|
-
super().__init__(
|
|
113
|
+
super().__init__(
|
|
114
|
+
server_url=server_url,
|
|
115
|
+
asr_config=asr_config,
|
|
116
|
+
tts_config=tts_config,
|
|
117
|
+
)
|
|
115
118
|
self.token = token
|
|
116
119
|
|
|
117
120
|
@classmethod
|
|
118
121
|
def from_credentials(
|
|
119
|
-
cls,
|
|
122
|
+
cls,
|
|
123
|
+
credentials: Optional[Dict[str, Any]],
|
|
120
124
|
) -> VoiceInputChannel:
|
|
121
125
|
if not credentials:
|
|
122
126
|
raise ValueError("No credentials given for Audiocodes voice channel.")
|
|
@@ -126,7 +130,6 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
|
|
|
126
130
|
server_url=credentials["server_url"],
|
|
127
131
|
asr_config=credentials["asr"],
|
|
128
132
|
tts_config=credentials["tts"],
|
|
129
|
-
monitor_silence=credentials.get("monitor_silence", False),
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
|
|
@@ -99,7 +99,8 @@ class GenesysInputChannel(VoiceInputChannel):
|
|
|
99
99
|
|
|
100
100
|
@classmethod
|
|
101
101
|
def from_credentials(
|
|
102
|
-
cls,
|
|
102
|
+
cls,
|
|
103
|
+
credentials: Optional[Dict[str, Any]],
|
|
103
104
|
) -> VoiceInputChannel:
|
|
104
105
|
if not credentials:
|
|
105
106
|
raise ValueError("No credentials given for Genesys voice channel.")
|
|
@@ -113,7 +114,6 @@ class GenesysInputChannel(VoiceInputChannel):
|
|
|
113
114
|
server_url=credentials["server_url"],
|
|
114
115
|
asr_config=credentials["asr"],
|
|
115
116
|
tts_config=credentials["tts"],
|
|
116
|
-
monitor_silence=credentials.get("monitor_silence", False),
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
def _ensure_channel_data_initialized(self) -> None:
|
|
@@ -14,7 +14,7 @@ from sanic import ( # type: ignore[attr-defined]
|
|
|
14
14
|
response,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
from rasa.core.channels import
|
|
17
|
+
from rasa.core.channels import UserMessage
|
|
18
18
|
from rasa.core.channels.channel import (
|
|
19
19
|
create_auth_requested_response_provider,
|
|
20
20
|
requires_basic_auth,
|
|
@@ -102,16 +102,22 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
|
|
|
102
102
|
server_url: str,
|
|
103
103
|
asr_config: Dict,
|
|
104
104
|
tts_config: Dict,
|
|
105
|
-
monitor_silence: bool = False,
|
|
106
105
|
username: Optional[Text] = None,
|
|
107
106
|
password: Optional[Text] = None,
|
|
108
107
|
):
|
|
109
|
-
super().__init__(
|
|
108
|
+
super().__init__(
|
|
109
|
+
server_url=server_url,
|
|
110
|
+
asr_config=asr_config,
|
|
111
|
+
tts_config=tts_config,
|
|
112
|
+
)
|
|
110
113
|
self.username = username
|
|
111
114
|
self.password = password
|
|
112
115
|
|
|
113
116
|
@classmethod
|
|
114
|
-
def from_credentials(
|
|
117
|
+
def from_credentials(
|
|
118
|
+
cls,
|
|
119
|
+
credentials: Optional[Dict[str, Any]],
|
|
120
|
+
) -> VoiceInputChannel:
|
|
115
121
|
credentials = credentials or {}
|
|
116
122
|
|
|
117
123
|
username = credentials.get("username")
|
|
@@ -126,7 +132,6 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
|
|
|
126
132
|
credentials["server_url"],
|
|
127
133
|
credentials["asr"],
|
|
128
134
|
credentials["tts"],
|
|
129
|
-
credentials.get("monitor_silence", False),
|
|
130
135
|
username=username,
|
|
131
136
|
password=password,
|
|
132
137
|
)
|
|
@@ -31,8 +31,10 @@ from rasa.core.channels.voice_stream.tts.azure import AzureTTS
|
|
|
31
31
|
from rasa.core.channels.voice_stream.tts.cartesia import CartesiaTTS
|
|
32
32
|
from rasa.core.channels.voice_stream.tts.tts_cache import TTSCache
|
|
33
33
|
from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine, TTSError
|
|
34
|
-
from rasa.core.channels.voice_stream.util import
|
|
35
|
-
|
|
34
|
+
from rasa.core.channels.voice_stream.util import (
|
|
35
|
+
generate_silence,
|
|
36
|
+
)
|
|
37
|
+
from rasa.shared.core.constants import SILENCE_TIMEOUT_SLOT
|
|
36
38
|
from rasa.shared.utils.cli import print_error_and_exit
|
|
37
39
|
from rasa.shared.utils.common import (
|
|
38
40
|
class_from_module_path,
|
|
@@ -171,8 +173,12 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
171
173
|
def update_silence_timeout(self) -> None:
|
|
172
174
|
"""Updates the silence timeout for the session."""
|
|
173
175
|
if self.tracker_state:
|
|
174
|
-
call_state.silence_timeout =
|
|
175
|
-
|
|
176
|
+
call_state.silence_timeout = self.tracker_state["slots"][ # type: ignore[attr-defined]
|
|
177
|
+
SILENCE_TIMEOUT_SLOT
|
|
178
|
+
]
|
|
179
|
+
logger.debug(
|
|
180
|
+
"voice_channel.silence_timeout_updated",
|
|
181
|
+
silence_timeout=call_state.silence_timeout,
|
|
176
182
|
)
|
|
177
183
|
|
|
178
184
|
async def send_text_with_buttons(
|
|
@@ -285,21 +291,24 @@ class VoiceInputChannel(InputChannel):
|
|
|
285
291
|
server_url: str,
|
|
286
292
|
asr_config: Dict,
|
|
287
293
|
tts_config: Dict,
|
|
288
|
-
monitor_silence: bool = False,
|
|
289
294
|
):
|
|
290
295
|
validate_voice_license_scope()
|
|
291
296
|
self.server_url = server_url
|
|
292
297
|
self.asr_config = asr_config
|
|
293
298
|
self.tts_config = tts_config
|
|
294
|
-
self.monitor_silence = monitor_silence
|
|
295
299
|
self.tts_cache = TTSCache(tts_config.get("cache_size", 1000))
|
|
296
300
|
|
|
301
|
+
logger.info(
|
|
302
|
+
"voice_channel.initialized",
|
|
303
|
+
server_url=self.server_url,
|
|
304
|
+
asr_config=self.asr_config,
|
|
305
|
+
tts_config=self.tts_config,
|
|
306
|
+
)
|
|
307
|
+
|
|
297
308
|
async def monitor_silence_timeout(self, asr_event_queue: asyncio.Queue) -> None:
|
|
298
309
|
timeout = call_state.silence_timeout
|
|
299
310
|
if not timeout:
|
|
300
311
|
return
|
|
301
|
-
if not self.monitor_silence:
|
|
302
|
-
return
|
|
303
312
|
logger.debug("voice_channel.silence_timeout_watch_started", timeout=timeout)
|
|
304
313
|
await asyncio.sleep(timeout)
|
|
305
314
|
await asr_event_queue.put(UserSilence())
|
|
@@ -314,13 +323,15 @@ class VoiceInputChannel(InputChannel):
|
|
|
314
323
|
call_state.silence_timeout_watcher = None # type: ignore[attr-defined]
|
|
315
324
|
|
|
316
325
|
@classmethod
|
|
317
|
-
def from_credentials(
|
|
326
|
+
def from_credentials(
|
|
327
|
+
cls,
|
|
328
|
+
credentials: Optional[Dict[str, Any]],
|
|
329
|
+
) -> InputChannel:
|
|
318
330
|
credentials = credentials or {}
|
|
319
331
|
return cls(
|
|
320
332
|
credentials["server_url"],
|
|
321
333
|
credentials["asr"],
|
|
322
334
|
credentials["tts"],
|
|
323
|
-
credentials.get("monitor_silence", False),
|
|
324
335
|
)
|
|
325
336
|
|
|
326
337
|
def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
|
|
@@ -340,9 +351,9 @@ class VoiceInputChannel(InputChannel):
|
|
|
340
351
|
) -> None:
|
|
341
352
|
output_channel = self.create_output_channel(channel_websocket, tts_engine)
|
|
342
353
|
message = UserMessage(
|
|
343
|
-
USER_CONVERSATION_SESSION_START,
|
|
344
|
-
output_channel,
|
|
345
|
-
call_parameters.stream_id,
|
|
354
|
+
text=USER_CONVERSATION_SESSION_START,
|
|
355
|
+
output_channel=output_channel,
|
|
356
|
+
sender_id=call_parameters.stream_id,
|
|
346
357
|
input_channel=self.name(),
|
|
347
358
|
metadata=asdict(call_parameters),
|
|
348
359
|
)
|
|
@@ -377,17 +388,17 @@ class VoiceInputChannel(InputChannel):
|
|
|
377
388
|
|
|
378
389
|
async def consume_audio_bytes() -> None:
|
|
379
390
|
async for message in channel_websocket:
|
|
380
|
-
|
|
391
|
+
was_bot_speaking_before = call_state.is_bot_speaking
|
|
381
392
|
channel_action = self.map_input_message(message, channel_websocket)
|
|
382
393
|
is_bot_speaking_after = call_state.is_bot_speaking
|
|
383
394
|
|
|
384
|
-
if not
|
|
395
|
+
if not was_bot_speaking_before and is_bot_speaking_after:
|
|
385
396
|
logger.debug("voice_channel.bot_started_speaking")
|
|
386
397
|
# relevant when the bot speaks multiple messages in one turn
|
|
387
398
|
self._cancel_silence_timeout_watcher()
|
|
388
399
|
|
|
389
400
|
# we just stopped speaking, starting a watcher for silence timeout
|
|
390
|
-
if
|
|
401
|
+
if was_bot_speaking_before and not is_bot_speaking_after:
|
|
391
402
|
logger.debug("voice_channel.bot_stopped_speaking")
|
|
392
403
|
self._cancel_silence_timeout_watcher()
|
|
393
404
|
call_state.silence_timeout_watcher = ( # type: ignore[attr-defined]
|
|
@@ -458,9 +469,9 @@ class VoiceInputChannel(InputChannel):
|
|
|
458
469
|
call_state.is_user_speaking = False # type: ignore[attr-defined]
|
|
459
470
|
output_channel = self.create_output_channel(voice_websocket, tts_engine)
|
|
460
471
|
message = UserMessage(
|
|
461
|
-
e.text,
|
|
462
|
-
output_channel,
|
|
463
|
-
call_parameters.stream_id,
|
|
472
|
+
text=e.text,
|
|
473
|
+
output_channel=output_channel,
|
|
474
|
+
sender_id=call_parameters.stream_id,
|
|
464
475
|
input_channel=self.name(),
|
|
465
476
|
metadata=asdict(call_parameters),
|
|
466
477
|
)
|
|
@@ -471,9 +482,9 @@ class VoiceInputChannel(InputChannel):
|
|
|
471
482
|
elif isinstance(e, UserSilence):
|
|
472
483
|
output_channel = self.create_output_channel(voice_websocket, tts_engine)
|
|
473
484
|
message = UserMessage(
|
|
474
|
-
USER_CONVERSATION_SILENCE_TIMEOUT,
|
|
475
|
-
output_channel,
|
|
476
|
-
call_parameters.stream_id,
|
|
485
|
+
text=USER_CONVERSATION_SILENCE_TIMEOUT,
|
|
486
|
+
output_channel=output_channel,
|
|
487
|
+
sender_id=call_parameters.stream_id,
|
|
477
488
|
input_channel=self.name(),
|
|
478
489
|
metadata=asdict(call_parameters),
|
|
479
490
|
)
|