rasa-pro 3.10.18__py3-none-any.whl → 3.10.20__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/cli/run.py +10 -6
- rasa/cli/utils.py +7 -0
- rasa/core/channels/audiocodes.py +43 -16
- rasa/core/channels/channel.py +104 -10
- rasa/core/channels/twilio_voice.py +57 -6
- rasa/core/policies/intentless_policy.py +5 -58
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -1
- rasa/dialogue_understanding/processor/command_processor.py +21 -5
- rasa/dialogue_understanding/processor/command_processor_component.py +5 -2
- rasa/e2e_test/utils/validation.py +3 -3
- rasa/engine/validation.py +44 -9
- rasa/model_training.py +2 -1
- rasa/shared/constants.py +3 -0
- rasa/shared/core/domain.py +12 -3
- rasa/shared/core/policies/__init__.py +0 -0
- rasa/shared/core/policies/utils.py +87 -0
- rasa/tracing/instrumentation/attribute_extractors.py +2 -0
- rasa/version.py +1 -1
- {rasa_pro-3.10.18.dist-info → rasa_pro-3.10.20.dist-info}/METADATA +6 -7
- {rasa_pro-3.10.18.dist-info → rasa_pro-3.10.20.dist-info}/RECORD +23 -23
- {rasa_pro-3.10.18.dist-info → rasa_pro-3.10.20.dist-info}/WHEEL +1 -1
- README.md +0 -41
- rasa/keys +0 -1
- {rasa_pro-3.10.18.dist-info → rasa_pro-3.10.20.dist-info}/NOTICE +0 -0
- {rasa_pro-3.10.18.dist-info → rasa_pro-3.10.20.dist-info}/entry_points.txt +0 -0
rasa/cli/run.py
CHANGED
|
@@ -62,12 +62,16 @@ def run_actions(args: argparse.Namespace) -> None:
|
|
|
62
62
|
|
|
63
63
|
def _validate_model_path(model_path: Text, parameter: Text, default: Text) -> Text:
|
|
64
64
|
if model_path is not None and not os.path.exists(model_path):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
raise ModelNotFound(
|
|
66
|
+
f"The provided model path '{model_path}' could not be found. "
|
|
67
|
+
"Provide an existing model path."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if model_path is None:
|
|
71
|
+
logger.debug(
|
|
72
|
+
f"Parameter '{parameter}' not set. "
|
|
73
|
+
"Using default location '{default}' instead."
|
|
74
|
+
)
|
|
71
75
|
os.makedirs(default, exist_ok=True)
|
|
72
76
|
model_path = default
|
|
73
77
|
|
rasa/cli/utils.py
CHANGED
|
@@ -14,6 +14,7 @@ import structlog
|
|
|
14
14
|
import rasa.shared.utils.cli
|
|
15
15
|
import rasa.shared.utils.io
|
|
16
16
|
from rasa import telemetry
|
|
17
|
+
from rasa.exceptions import ModelNotFound
|
|
17
18
|
from rasa.shared.constants import (
|
|
18
19
|
ASSISTANT_ID_DEFAULT_VALUE,
|
|
19
20
|
ASSISTANT_ID_KEY,
|
|
@@ -76,6 +77,12 @@ def get_validated_path(
|
|
|
76
77
|
if current and os.path.exists(current):
|
|
77
78
|
return current
|
|
78
79
|
|
|
80
|
+
if parameter == "model":
|
|
81
|
+
raise ModelNotFound(
|
|
82
|
+
f"The provided model path '{current}' could not be found. "
|
|
83
|
+
"Provide an existing model path."
|
|
84
|
+
)
|
|
85
|
+
|
|
79
86
|
# try to find a valid option among the defaults
|
|
80
87
|
if isinstance(default, str) or isinstance(default, Path):
|
|
81
88
|
default_options = [str(default)]
|
rasa/core/channels/audiocodes.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import datetime
|
|
3
|
+
import hmac
|
|
3
4
|
import json
|
|
4
5
|
import logging
|
|
5
6
|
import uuid
|
|
@@ -7,16 +8,16 @@ from typing import Any, Awaitable, Callable, Dict, List, Optional, Text, Union
|
|
|
7
8
|
|
|
8
9
|
import structlog
|
|
9
10
|
from jsonschema import ValidationError, validate
|
|
10
|
-
from rasa.core import jobs
|
|
11
|
-
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
12
|
-
from rasa.core.channels.voice_aware.utils import validate_voice_license_scope
|
|
13
|
-
from rasa.shared.constants import INTENT_MESSAGE_PREFIX
|
|
14
|
-
from rasa.shared.exceptions import RasaException
|
|
15
11
|
from sanic import Blueprint, response
|
|
16
12
|
from sanic.exceptions import NotFound, SanicException, ServerError
|
|
17
13
|
from sanic.request import Request
|
|
18
14
|
from sanic.response import HTTPResponse
|
|
19
15
|
|
|
16
|
+
from rasa.core import jobs
|
|
17
|
+
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
18
|
+
from rasa.core.channels.voice_aware.utils import validate_voice_license_scope
|
|
19
|
+
from rasa.shared.constants import INTENT_MESSAGE_PREFIX
|
|
20
|
+
from rasa.shared.exceptions import RasaException
|
|
20
21
|
|
|
21
22
|
logger = logging.getLogger(__name__)
|
|
22
23
|
structlogger = structlog.get_logger()
|
|
@@ -72,9 +73,16 @@ class Conversation:
|
|
|
72
73
|
async def handle_activities(
|
|
73
74
|
self,
|
|
74
75
|
message: Dict[Text, Any],
|
|
76
|
+
input_channel_name: str,
|
|
75
77
|
output_channel: OutputChannel,
|
|
76
78
|
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
77
79
|
) -> None:
|
|
80
|
+
if input_channel_name == "":
|
|
81
|
+
logger.warning(
|
|
82
|
+
f"Audiocodes input channel name is empty "
|
|
83
|
+
f"for conversation {self.conversation_id}"
|
|
84
|
+
)
|
|
85
|
+
|
|
78
86
|
logger.debug("(handle_activities) --- Activities:")
|
|
79
87
|
for activity in message["activities"]:
|
|
80
88
|
text = None
|
|
@@ -99,6 +107,7 @@ class Conversation:
|
|
|
99
107
|
metadata = self.get_metadata(activity)
|
|
100
108
|
user_msg = UserMessage(
|
|
101
109
|
text=text,
|
|
110
|
+
input_channel=input_channel_name,
|
|
102
111
|
output_channel=output_channel,
|
|
103
112
|
sender_id=self.conversation_id,
|
|
104
113
|
metadata=metadata,
|
|
@@ -190,7 +199,11 @@ class AudiocodesInput(InputChannel):
|
|
|
190
199
|
|
|
191
200
|
def _check_token(self, token: Optional[Text]) -> None:
|
|
192
201
|
if not token:
|
|
202
|
+
structlogger.error("audiocodes.token_not_provided")
|
|
193
203
|
raise Unauthorized("Authentication token required.")
|
|
204
|
+
if not hmac.compare_digest(str(token), str(self.token)):
|
|
205
|
+
structlogger.error("audiocodes.invalid_token", invalid_token=token)
|
|
206
|
+
raise Unauthorized("Invalid authentication token.")
|
|
194
207
|
|
|
195
208
|
def _get_conversation(
|
|
196
209
|
self, token: Optional[Text], conversation_id: Text
|
|
@@ -321,6 +334,7 @@ class AudiocodesInput(InputChannel):
|
|
|
321
334
|
)
|
|
322
335
|
await conversation.handle_activities(
|
|
323
336
|
request.json,
|
|
337
|
+
input_channel_name=self.name(),
|
|
324
338
|
output_channel=ac_output,
|
|
325
339
|
on_new_message=on_new_message,
|
|
326
340
|
)
|
|
@@ -330,6 +344,7 @@ class AudiocodesInput(InputChannel):
|
|
|
330
344
|
ac_output = AudiocodesOutput()
|
|
331
345
|
await conversation.handle_activities(
|
|
332
346
|
request.json,
|
|
347
|
+
input_channel_name=self.name(),
|
|
333
348
|
output_channel=ac_output,
|
|
334
349
|
on_new_message=on_new_message,
|
|
335
350
|
)
|
|
@@ -349,18 +364,9 @@ class AudiocodesInput(InputChannel):
|
|
|
349
364
|
Example of payload:
|
|
350
365
|
{"conversation": <conversation_id>, "reason": Optional[Text]}.
|
|
351
366
|
"""
|
|
352
|
-
self.
|
|
353
|
-
|
|
354
|
-
await on_new_message(
|
|
355
|
-
UserMessage(
|
|
356
|
-
text=f"{INTENT_MESSAGE_PREFIX}vaig_event_end{reason}",
|
|
357
|
-
output_channel=None,
|
|
358
|
-
sender_id=conversation_id,
|
|
359
|
-
)
|
|
367
|
+
return await self._handle_disconnect(
|
|
368
|
+
request, conversation_id, on_new_message
|
|
360
369
|
)
|
|
361
|
-
del self.conversations[conversation_id]
|
|
362
|
-
logger.debug("(disconnect) --- Conversation was deleted")
|
|
363
|
-
return response.json({})
|
|
364
370
|
|
|
365
371
|
@ac_webhook.route("/conversation/<conversation_id>/keepalive", methods=["POST"])
|
|
366
372
|
async def keepalive(request: Request, conversation_id: Text) -> HTTPResponse:
|
|
@@ -375,6 +381,27 @@ class AudiocodesInput(InputChannel):
|
|
|
375
381
|
|
|
376
382
|
return ac_webhook
|
|
377
383
|
|
|
384
|
+
async def _handle_disconnect(
|
|
385
|
+
self,
|
|
386
|
+
request: Request,
|
|
387
|
+
conversation_id: Text,
|
|
388
|
+
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
389
|
+
) -> HTTPResponse:
|
|
390
|
+
"""Triggered when the call is disconnected."""
|
|
391
|
+
self._get_conversation(request.token, conversation_id)
|
|
392
|
+
reason = json.dumps({"reason": request.json.get("reason")})
|
|
393
|
+
await on_new_message(
|
|
394
|
+
UserMessage(
|
|
395
|
+
text=f"{INTENT_MESSAGE_PREFIX}vaig_event_end{reason}",
|
|
396
|
+
input_channel=self.name(),
|
|
397
|
+
output_channel=None,
|
|
398
|
+
sender_id=conversation_id,
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
del self.conversations[conversation_id]
|
|
402
|
+
logger.debug("(disconnect) --- Conversation was deleted")
|
|
403
|
+
return response.json({})
|
|
404
|
+
|
|
378
405
|
|
|
379
406
|
class AudiocodesOutput(OutputChannel):
|
|
380
407
|
@classmethod
|
rasa/core/channels/channel.py
CHANGED
|
@@ -1,29 +1,36 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hmac
|
|
1
4
|
import json
|
|
2
5
|
import logging
|
|
3
6
|
import uuid
|
|
4
|
-
import
|
|
5
|
-
from
|
|
6
|
-
from sanic.request import Request
|
|
7
|
+
from base64 import b64encode
|
|
8
|
+
from functools import wraps
|
|
7
9
|
from typing import (
|
|
8
|
-
Text,
|
|
9
|
-
List,
|
|
10
|
-
Dict,
|
|
11
10
|
Any,
|
|
12
|
-
|
|
11
|
+
Awaitable,
|
|
13
12
|
Callable,
|
|
13
|
+
Dict,
|
|
14
14
|
Iterable,
|
|
15
|
-
|
|
15
|
+
List,
|
|
16
16
|
NoReturn,
|
|
17
|
+
Optional,
|
|
18
|
+
Text,
|
|
17
19
|
)
|
|
18
20
|
|
|
21
|
+
import jwt
|
|
22
|
+
from sanic import Blueprint, Sanic
|
|
23
|
+
from sanic.exceptions import Unauthorized
|
|
24
|
+
from sanic.request import Request
|
|
25
|
+
|
|
19
26
|
from rasa.cli import utils as cli_utils
|
|
20
|
-
from rasa.shared.constants import DOCS_BASE_URL, DEFAULT_SENDER_ID
|
|
21
27
|
from rasa.core.constants import BEARER_TOKEN_PREFIX
|
|
22
|
-
from rasa.shared.
|
|
28
|
+
from rasa.shared.constants import DEFAULT_SENDER_ID, DOCS_BASE_URL
|
|
23
29
|
from rasa.shared.core.trackers import (
|
|
24
30
|
DialogueStateTracker,
|
|
25
31
|
EventVerbosity,
|
|
26
32
|
)
|
|
33
|
+
from rasa.shared.exceptions import RasaException
|
|
27
34
|
|
|
28
35
|
try:
|
|
29
36
|
from urlparse import urljoin
|
|
@@ -417,3 +424,90 @@ class CollectingOutputChannel(OutputChannel):
|
|
|
417
424
|
self, recipient_id: Text, json_message: Dict[Text, Any], **kwargs: Any
|
|
418
425
|
) -> None:
|
|
419
426
|
await self._persist_message(self._message(recipient_id, custom=json_message))
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
BASIC_AUTH_SCHEME = "Basic"
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def create_auth_requested_response_provider(
|
|
433
|
+
realm: str,
|
|
434
|
+
) -> Callable[[Request, Any, Any], ResponseWithAuthRequested]:
|
|
435
|
+
def _provider(
|
|
436
|
+
request: Request, *args: Any, **kwargs: Any
|
|
437
|
+
) -> ResponseWithAuthRequested:
|
|
438
|
+
return ResponseWithAuthRequested(scheme=BASIC_AUTH_SCHEME, realm=realm)
|
|
439
|
+
|
|
440
|
+
return _provider
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class ResponseWithAuthRequested(Unauthorized):
|
|
444
|
+
"""Custom exception to request authentication."""
|
|
445
|
+
|
|
446
|
+
def __init__(self, scheme: str, realm: str) -> None:
|
|
447
|
+
super().__init__(
|
|
448
|
+
message="Authentication requested.", scheme=scheme, realm=realm
|
|
449
|
+
) # type: ignore[no-untyped-call]
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def requires_basic_auth(
|
|
453
|
+
username: Optional[Text],
|
|
454
|
+
password: Optional[Text],
|
|
455
|
+
auth_request_provider: Optional[Callable[[Request, Any, Any], Unauthorized]] = None,
|
|
456
|
+
) -> Callable:
|
|
457
|
+
"""Decorator to require basic auth for a route.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
username: The username to check against.
|
|
461
|
+
password: The password to check against.
|
|
462
|
+
auth_request_provider: Optional function to provide a custom
|
|
463
|
+
response when authentication is requested. This function should
|
|
464
|
+
return an instance of `Unauthorized` with the necessary
|
|
465
|
+
authentication headers.
|
|
466
|
+
Returns:
|
|
467
|
+
A decorator that checks for basic authentication.
|
|
468
|
+
|
|
469
|
+
Raises:
|
|
470
|
+
Unauthorized: If the authentication fails or if authentication is
|
|
471
|
+
requested without necessary credentials (headers).
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
def decorator(func: Callable) -> Callable:
|
|
475
|
+
@wraps(func)
|
|
476
|
+
async def wrapper(request: Request, *args: Any, **kwargs: Any) -> Any:
|
|
477
|
+
if not username or not password:
|
|
478
|
+
return await func(request, *args, **kwargs)
|
|
479
|
+
|
|
480
|
+
auth_header = request.headers.get("Authorization")
|
|
481
|
+
|
|
482
|
+
# Some systems will first send a request without an authorization header
|
|
483
|
+
# to check if the endpoint is available. In this case, we need to
|
|
484
|
+
# return am Unauthorized response with the necessary authorization header
|
|
485
|
+
# to indicate that the endpoint requires authorization.
|
|
486
|
+
if not auth_header and auth_request_provider:
|
|
487
|
+
# if the request does not contain an authorization header,
|
|
488
|
+
# we raise an exception to request authorization
|
|
489
|
+
|
|
490
|
+
exception = auth_request_provider(request, *args, **kwargs)
|
|
491
|
+
logger.debug(
|
|
492
|
+
f"Responding with {exception.status_code} and "
|
|
493
|
+
f"necessary auth headers {exception.headers}"
|
|
494
|
+
)
|
|
495
|
+
raise exception
|
|
496
|
+
|
|
497
|
+
if not auth_header or not auth_header.startswith("Basic "):
|
|
498
|
+
logger.error("Missing or invalid authorization header.")
|
|
499
|
+
raise Unauthorized("Missing or invalid authorization header.") # type: ignore[no-untyped-call]
|
|
500
|
+
|
|
501
|
+
encoded = b64encode(f"{username}:{password}".encode()).decode()
|
|
502
|
+
username_password_digest: str = auth_header[len(BASIC_AUTH_SCHEME) :]
|
|
503
|
+
username_password_digest = username_password_digest.strip()
|
|
504
|
+
|
|
505
|
+
if not hmac.compare_digest(username_password_digest, encoded):
|
|
506
|
+
logger.error("Invalid username or password.")
|
|
507
|
+
raise Unauthorized("Invalid username or password.") # type: ignore[no-untyped-call]
|
|
508
|
+
|
|
509
|
+
return await func(request, *args, **kwargs)
|
|
510
|
+
|
|
511
|
+
return wrapper
|
|
512
|
+
|
|
513
|
+
return decorator
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Text
|
|
2
|
+
|
|
3
|
+
import structlog
|
|
1
4
|
from sanic import Blueprint, response
|
|
2
5
|
from sanic.request import Request
|
|
3
6
|
from sanic.response import HTTPResponse
|
|
4
|
-
from twilio.twiml.voice_response import
|
|
5
|
-
from typing import Text, Callable, Awaitable, List, Any, Dict, Optional
|
|
7
|
+
from twilio.twiml.voice_response import Gather, VoiceResponse
|
|
6
8
|
|
|
7
|
-
import rasa.utils.io
|
|
8
9
|
import rasa.shared.utils.io
|
|
9
|
-
|
|
10
|
-
from rasa.shared.exceptions import InvalidConfigException
|
|
10
|
+
import rasa.utils.io
|
|
11
11
|
from rasa.core.channels.channel import (
|
|
12
|
-
InputChannel,
|
|
13
12
|
CollectingOutputChannel,
|
|
13
|
+
InputChannel,
|
|
14
14
|
UserMessage,
|
|
15
|
+
create_auth_requested_response_provider,
|
|
16
|
+
requires_basic_auth,
|
|
15
17
|
)
|
|
18
|
+
from rasa.shared.core.events import BotUttered
|
|
19
|
+
from rasa.shared.exceptions import InvalidConfigException, RasaException
|
|
20
|
+
|
|
21
|
+
logger = structlog.get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
TWILIO_VOICE_PATH = "webhooks/twilio_voice/webhook"
|
|
16
25
|
|
|
17
26
|
|
|
18
27
|
class TwilioVoiceInput(InputChannel):
|
|
@@ -104,6 +113,14 @@ class TwilioVoiceInput(InputChannel):
|
|
|
104
113
|
"""Load custom configurations."""
|
|
105
114
|
credentials = credentials or {}
|
|
106
115
|
|
|
116
|
+
username = credentials.get("username")
|
|
117
|
+
password = credentials.get("password")
|
|
118
|
+
if (username is None) != (password is None):
|
|
119
|
+
raise RasaException(
|
|
120
|
+
"In TwilioVoice channel, either both username and password "
|
|
121
|
+
"or neither should be provided. "
|
|
122
|
+
)
|
|
123
|
+
|
|
107
124
|
return cls(
|
|
108
125
|
credentials.get("initial_prompt", "hello"),
|
|
109
126
|
credentials.get(
|
|
@@ -114,6 +131,8 @@ class TwilioVoiceInput(InputChannel):
|
|
|
114
131
|
credentials.get("speech_timeout", "5"),
|
|
115
132
|
credentials.get("speech_model", "default"),
|
|
116
133
|
credentials.get("enhanced", "false"),
|
|
134
|
+
username=username,
|
|
135
|
+
password=password,
|
|
117
136
|
)
|
|
118
137
|
|
|
119
138
|
def __init__(
|
|
@@ -124,6 +143,8 @@ class TwilioVoiceInput(InputChannel):
|
|
|
124
143
|
speech_timeout: Text = "5",
|
|
125
144
|
speech_model: Text = "default",
|
|
126
145
|
enhanced: Text = "false",
|
|
146
|
+
username: Optional[Text] = None,
|
|
147
|
+
password: Optional[Text] = None,
|
|
127
148
|
) -> None:
|
|
128
149
|
"""Creates a connection to Twilio voice.
|
|
129
150
|
|
|
@@ -141,6 +162,8 @@ class TwilioVoiceInput(InputChannel):
|
|
|
141
162
|
self.speech_timeout = speech_timeout
|
|
142
163
|
self.speech_model = speech_model
|
|
143
164
|
self.enhanced = enhanced
|
|
165
|
+
self.username = username
|
|
166
|
+
self.password = password
|
|
144
167
|
|
|
145
168
|
self._validate_configuration()
|
|
146
169
|
|
|
@@ -149,6 +172,9 @@ class TwilioVoiceInput(InputChannel):
|
|
|
149
172
|
if self.assistant_voice not in self.SUPPORTED_VOICES:
|
|
150
173
|
self._raise_invalid_voice_exception()
|
|
151
174
|
|
|
175
|
+
if (self.username is None) != (self.password is None):
|
|
176
|
+
self._raise_invalid_credentials_exception()
|
|
177
|
+
|
|
152
178
|
try:
|
|
153
179
|
int(self.speech_timeout)
|
|
154
180
|
except ValueError:
|
|
@@ -234,6 +260,13 @@ class TwilioVoiceInput(InputChannel):
|
|
|
234
260
|
return response.json({"status": "ok"})
|
|
235
261
|
|
|
236
262
|
@twilio_voice_webhook.route("/webhook", methods=["POST"])
|
|
263
|
+
@requires_basic_auth(
|
|
264
|
+
username=self.username,
|
|
265
|
+
password=self.password,
|
|
266
|
+
auth_request_provider=create_auth_requested_response_provider(
|
|
267
|
+
TWILIO_VOICE_PATH
|
|
268
|
+
),
|
|
269
|
+
)
|
|
237
270
|
async def receive(request: Request) -> HTTPResponse:
|
|
238
271
|
sender_id = request.form.get("From")
|
|
239
272
|
text = request.form.get("SpeechResult")
|
|
@@ -277,6 +310,11 @@ class TwilioVoiceInput(InputChannel):
|
|
|
277
310
|
twilio_response = self._build_twilio_voice_response(
|
|
278
311
|
[{"text": last_response_text}]
|
|
279
312
|
)
|
|
313
|
+
|
|
314
|
+
logger.debug(
|
|
315
|
+
"twilio_voice.webhook.twilio_response",
|
|
316
|
+
twilio_response=str(twilio_response),
|
|
317
|
+
)
|
|
280
318
|
return response.text(str(twilio_response), content_type="text/xml")
|
|
281
319
|
|
|
282
320
|
return twilio_voice_webhook
|
|
@@ -295,6 +333,13 @@ class TwilioVoiceInput(InputChannel):
|
|
|
295
333
|
enhanced=self.enhanced,
|
|
296
334
|
)
|
|
297
335
|
|
|
336
|
+
if not messages:
|
|
337
|
+
# In case bot has a greet message disabled
|
|
338
|
+
# or if the bot is not configured to send an initial message
|
|
339
|
+
# we need to send a voice response with speech settings
|
|
340
|
+
voice_response.append(gather)
|
|
341
|
+
return voice_response
|
|
342
|
+
|
|
298
343
|
# Add pauses between messages.
|
|
299
344
|
# Add a listener to the last message to listen for user response.
|
|
300
345
|
for i, message in enumerate(messages):
|
|
@@ -308,6 +353,12 @@ class TwilioVoiceInput(InputChannel):
|
|
|
308
353
|
|
|
309
354
|
return voice_response
|
|
310
355
|
|
|
356
|
+
def _raise_invalid_credentials_exception(self) -> None:
|
|
357
|
+
raise InvalidConfigException(
|
|
358
|
+
"In TwilioVoice channel, either both username and password "
|
|
359
|
+
"or neither should be provided. "
|
|
360
|
+
)
|
|
361
|
+
|
|
311
362
|
|
|
312
363
|
class TwilioVoiceCollectingOutputChannel(CollectingOutputChannel):
|
|
313
364
|
"""Output channel that collects send messages in a list.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import importlib.resources
|
|
2
2
|
import math
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any, Dict, List, Optional,
|
|
4
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Text, Tuple
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
7
|
import tiktoken
|
|
@@ -29,7 +29,6 @@ from rasa.engine.storage.storage import ModelStorage
|
|
|
29
29
|
from rasa.graph_components.providers.forms_provider import Forms
|
|
30
30
|
from rasa.graph_components.providers.responses_provider import Responses
|
|
31
31
|
from rasa.shared.constants import (
|
|
32
|
-
REQUIRED_SLOTS_KEY,
|
|
33
32
|
EMBEDDINGS_CONFIG_KEY,
|
|
34
33
|
LLM_CONFIG_KEY,
|
|
35
34
|
MODEL_CONFIG_KEY,
|
|
@@ -49,6 +48,7 @@ from rasa.shared.core.events import (
|
|
|
49
48
|
)
|
|
50
49
|
from rasa.shared.core.flows import FlowsList
|
|
51
50
|
from rasa.shared.core.generator import TrackerWithCachedStates
|
|
51
|
+
from rasa.shared.core.policies.utils import filter_responses_for_intentless_policy
|
|
52
52
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
53
53
|
from rasa.shared.exceptions import FileIOException, RasaCoreException
|
|
54
54
|
from rasa.shared.nlu.constants import PREDICTED_CONFIDENCE_KEY
|
|
@@ -81,8 +81,6 @@ from rasa.utils.ml_utils import (
|
|
|
81
81
|
persist_faiss_vector_store,
|
|
82
82
|
response_for_template,
|
|
83
83
|
)
|
|
84
|
-
from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
85
|
-
from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT
|
|
86
84
|
from rasa.utils.log_utils import log_llm
|
|
87
85
|
|
|
88
86
|
if TYPE_CHECKING:
|
|
@@ -142,59 +140,6 @@ class Conversation:
|
|
|
142
140
|
interactions: List[Interaction] = field(default_factory=list)
|
|
143
141
|
|
|
144
142
|
|
|
145
|
-
def collect_form_responses(forms: Forms) -> Set[Text]:
|
|
146
|
-
"""Collect responses that belong the requested slots in forms.
|
|
147
|
-
|
|
148
|
-
Args:
|
|
149
|
-
forms: the forms from the domain
|
|
150
|
-
Returns:
|
|
151
|
-
all utterances used in forms
|
|
152
|
-
"""
|
|
153
|
-
form_responses = set()
|
|
154
|
-
for _, form_info in forms.data.items():
|
|
155
|
-
for required_slot in form_info.get(REQUIRED_SLOTS_KEY, []):
|
|
156
|
-
form_responses.add(f"utter_ask_{required_slot}")
|
|
157
|
-
return form_responses
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def filter_responses(responses: Responses, forms: Forms, flows: FlowsList) -> Responses:
|
|
161
|
-
"""Filters out responses that are unwanted for the intentless policy.
|
|
162
|
-
|
|
163
|
-
This includes utterances used in flows and forms.
|
|
164
|
-
|
|
165
|
-
Args:
|
|
166
|
-
responses: the responses from the domain
|
|
167
|
-
forms: the forms from the domain
|
|
168
|
-
flows: all flows
|
|
169
|
-
Returns:
|
|
170
|
-
The remaining, relevant responses for the intentless policy.
|
|
171
|
-
"""
|
|
172
|
-
form_responses = collect_form_responses(forms)
|
|
173
|
-
flow_responses = flows.utterances
|
|
174
|
-
combined_responses = form_responses | flow_responses
|
|
175
|
-
filtered_responses = {
|
|
176
|
-
name: variants
|
|
177
|
-
for name, variants in responses.data.items()
|
|
178
|
-
if name not in combined_responses
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
pattern_chitchat = flows.flow_by_id(FLOW_PATTERN_CHITCHAT)
|
|
182
|
-
|
|
183
|
-
# The following condition is highly unlikely, but mypy requires the case
|
|
184
|
-
# of pattern_chitchat == None to be addressed
|
|
185
|
-
if not pattern_chitchat:
|
|
186
|
-
return Responses(data=filtered_responses)
|
|
187
|
-
|
|
188
|
-
# if action_trigger_chitchat, filter out "utter_free_chitchat_response"
|
|
189
|
-
has_action_trigger_chitchat = pattern_chitchat.has_action_step(
|
|
190
|
-
ACTION_TRIGGER_CHITCHAT
|
|
191
|
-
)
|
|
192
|
-
if has_action_trigger_chitchat:
|
|
193
|
-
filtered_responses.pop("utter_free_chitchat_response", None)
|
|
194
|
-
|
|
195
|
-
return Responses(data=filtered_responses)
|
|
196
|
-
|
|
197
|
-
|
|
198
143
|
def action_from_response(
|
|
199
144
|
text: Optional[str], responses: Dict[Text, List[Dict[Text, Any]]]
|
|
200
145
|
) -> Optional[str]:
|
|
@@ -495,7 +440,9 @@ class IntentlessPolicy(Policy):
|
|
|
495
440
|
"IntentlessPolicy",
|
|
496
441
|
)
|
|
497
442
|
|
|
498
|
-
responses =
|
|
443
|
+
responses = filter_responses_for_intentless_policy(
|
|
444
|
+
responses, forms, flows or FlowsList([])
|
|
445
|
+
)
|
|
499
446
|
telemetry.track_intentless_policy_train()
|
|
500
447
|
response_texts = [r for r in extract_ai_response_examples(responses.data)]
|
|
501
448
|
|
|
@@ -139,7 +139,7 @@ class NLUCommandAdapter(GraphComponent, CommandGenerator):
|
|
|
139
139
|
|
|
140
140
|
if commands:
|
|
141
141
|
commands = clean_up_commands(
|
|
142
|
-
commands, tracker, flows, self._execution_context
|
|
142
|
+
commands, tracker, flows, self._execution_context, domain
|
|
143
143
|
)
|
|
144
144
|
log_llm(
|
|
145
145
|
logger=structlogger,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import List, Optional, Type, Set, Dict
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
|
+
|
|
5
|
+
from rasa.shared.core.domain import Domain
|
|
4
6
|
from rasa.shared.core.training_data.structures import StoryGraph
|
|
5
7
|
from rasa.dialogue_understanding.commands import (
|
|
6
8
|
CancelFlowCommand,
|
|
@@ -43,6 +45,7 @@ from rasa.shared.core.constants import FLOW_HASHES_SLOT
|
|
|
43
45
|
from rasa.shared.core.events import Event, SlotSet
|
|
44
46
|
from rasa.shared.core.flows import FlowsList
|
|
45
47
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
48
|
+
from rasa.shared.core.policies.utils import contains_intentless_policy_responses
|
|
46
49
|
from rasa.shared.core.slots import Slot
|
|
47
50
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
48
51
|
from rasa.shared.nlu.constants import COMMANDS
|
|
@@ -181,6 +184,7 @@ def execute_commands(
|
|
|
181
184
|
all_flows: FlowsList,
|
|
182
185
|
execution_context: ExecutionContext,
|
|
183
186
|
story_graph: Optional[StoryGraph] = None,
|
|
187
|
+
domain: Optional[Domain] = None,
|
|
184
188
|
) -> List[Event]:
|
|
185
189
|
"""Executes a list of commands.
|
|
186
190
|
|
|
@@ -190,6 +194,7 @@ def execute_commands(
|
|
|
190
194
|
all_flows: All flows.
|
|
191
195
|
execution_context: Information about the single graph run.
|
|
192
196
|
story_graph: StoryGraph object with stories available for training.
|
|
197
|
+
domain: The domain of the bot.
|
|
193
198
|
|
|
194
199
|
Returns:
|
|
195
200
|
A list of the events that were created.
|
|
@@ -198,7 +203,7 @@ def execute_commands(
|
|
|
198
203
|
original_tracker = tracker.copy()
|
|
199
204
|
|
|
200
205
|
commands = clean_up_commands(
|
|
201
|
-
commands, tracker, all_flows, execution_context, story_graph
|
|
206
|
+
commands, tracker, all_flows, execution_context, story_graph, domain
|
|
202
207
|
)
|
|
203
208
|
|
|
204
209
|
updated_flows = find_updated_flows(tracker, all_flows)
|
|
@@ -332,6 +337,7 @@ def clean_up_commands(
|
|
|
332
337
|
all_flows: FlowsList,
|
|
333
338
|
execution_context: ExecutionContext,
|
|
334
339
|
story_graph: Optional[StoryGraph] = None,
|
|
340
|
+
domain: Optional[Domain] = None,
|
|
335
341
|
) -> List[Command]:
|
|
336
342
|
"""Clean up a list of commands.
|
|
337
343
|
|
|
@@ -347,10 +353,13 @@ def clean_up_commands(
|
|
|
347
353
|
all_flows: All flows.
|
|
348
354
|
execution_context: Information about a single graph run.
|
|
349
355
|
story_graph: StoryGraph object with stories available for training.
|
|
356
|
+
domain: The domain of the bot.
|
|
350
357
|
|
|
351
358
|
Returns:
|
|
352
359
|
The cleaned up commands.
|
|
353
360
|
"""
|
|
361
|
+
domain = domain if domain else Domain.empty()
|
|
362
|
+
|
|
354
363
|
slots_so_far, active_flow = filled_slots_for_active_flow(tracker, all_flows)
|
|
355
364
|
|
|
356
365
|
clean_commands: List[Command] = []
|
|
@@ -393,7 +402,12 @@ def clean_up_commands(
|
|
|
393
402
|
# handle chitchat command differently from other free-form answer commands
|
|
394
403
|
elif isinstance(command, ChitChatAnswerCommand):
|
|
395
404
|
clean_commands = clean_up_chitchat_command(
|
|
396
|
-
clean_commands,
|
|
405
|
+
clean_commands,
|
|
406
|
+
command,
|
|
407
|
+
all_flows,
|
|
408
|
+
execution_context,
|
|
409
|
+
domain,
|
|
410
|
+
story_graph,
|
|
397
411
|
)
|
|
398
412
|
|
|
399
413
|
elif isinstance(command, FreeFormAnswerCommand):
|
|
@@ -570,6 +584,7 @@ def clean_up_chitchat_command(
|
|
|
570
584
|
command: ChitChatAnswerCommand,
|
|
571
585
|
flows: FlowsList,
|
|
572
586
|
execution_context: ExecutionContext,
|
|
587
|
+
domain: Domain,
|
|
573
588
|
story_graph: Optional[StoryGraph] = None,
|
|
574
589
|
) -> List[Command]:
|
|
575
590
|
"""Clean up a chitchat answer command.
|
|
@@ -583,6 +598,8 @@ def clean_up_chitchat_command(
|
|
|
583
598
|
flows: All flows.
|
|
584
599
|
execution_context: Information about a single graph run.
|
|
585
600
|
story_graph: StoryGraph object with stories available for training.
|
|
601
|
+
domain: The domain of the bot.
|
|
602
|
+
|
|
586
603
|
Returns:
|
|
587
604
|
The cleaned up commands.
|
|
588
605
|
"""
|
|
@@ -608,10 +625,9 @@ def clean_up_chitchat_command(
|
|
|
608
625
|
)
|
|
609
626
|
defines_intentless_policy = execution_context.has_node(IntentlessPolicy)
|
|
610
627
|
|
|
611
|
-
has_e2e_stories = True if (story_graph and story_graph.has_e2e_stories()) else False
|
|
612
|
-
|
|
613
628
|
if (has_action_trigger_chitchat and not defines_intentless_policy) or (
|
|
614
|
-
defines_intentless_policy
|
|
629
|
+
defines_intentless_policy
|
|
630
|
+
and not contains_intentless_policy_responses(flows, domain, story_graph)
|
|
615
631
|
):
|
|
616
632
|
resulting_commands.insert(
|
|
617
633
|
0, CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_CHITCHAT)
|
|
@@ -6,6 +6,7 @@ import rasa.dialogue_understanding.processor.command_processor
|
|
|
6
6
|
from rasa.engine.graph import ExecutionContext, GraphComponent
|
|
7
7
|
from rasa.engine.storage.resource import Resource
|
|
8
8
|
from rasa.engine.storage.storage import ModelStorage
|
|
9
|
+
from rasa.shared.core.domain import Domain
|
|
9
10
|
from rasa.shared.core.events import Event
|
|
10
11
|
from rasa.shared.core.flows import FlowsList
|
|
11
12
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -15,7 +16,8 @@ from rasa.shared.core.training_data.structures import StoryGraph
|
|
|
15
16
|
class CommandProcessorComponent(GraphComponent):
|
|
16
17
|
"""Processes commands by issuing events to modify a tracker.
|
|
17
18
|
|
|
18
|
-
Minimal component that applies commands to a tracker.
|
|
19
|
+
Minimal component that applies commands to a tracker.
|
|
20
|
+
"""
|
|
19
21
|
|
|
20
22
|
def __init__(self, execution_context: ExecutionContext):
|
|
21
23
|
self._execution_context = execution_context
|
|
@@ -36,8 +38,9 @@ class CommandProcessorComponent(GraphComponent):
|
|
|
36
38
|
tracker: DialogueStateTracker,
|
|
37
39
|
flows: FlowsList,
|
|
38
40
|
story_graph: StoryGraph,
|
|
41
|
+
domain: Domain,
|
|
39
42
|
) -> List[Event]:
|
|
40
43
|
"""Execute commands to update tracker state."""
|
|
41
44
|
return rasa.dialogue_understanding.processor.command_processor.execute_commands(
|
|
42
|
-
tracker, flows, self._execution_context, story_graph
|
|
45
|
+
tracker, flows, self._execution_context, story_graph, domain
|
|
43
46
|
)
|
|
@@ -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.exceptions import ModelNotFound
|
|
9
10
|
from rasa.shared.utils.yaml import read_schema_file
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
@@ -54,10 +55,9 @@ def validate_model_path(model_path: Optional[str], parameter: str, default: str)
|
|
|
54
55
|
return model_path
|
|
55
56
|
|
|
56
57
|
if model_path and not Path(model_path).exists():
|
|
57
|
-
|
|
58
|
+
raise ModelNotFound(
|
|
58
59
|
f"The provided model path '{model_path}' could not be found. "
|
|
59
|
-
|
|
60
|
-
UserWarning,
|
|
60
|
+
"Provide an existing model path."
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
elif model_path is None:
|
rasa/engine/validation.py
CHANGED
|
@@ -5,18 +5,18 @@ import logging
|
|
|
5
5
|
import sys
|
|
6
6
|
import typing
|
|
7
7
|
from typing import (
|
|
8
|
-
|
|
8
|
+
Any,
|
|
9
9
|
Callable,
|
|
10
|
+
Dict,
|
|
11
|
+
List,
|
|
12
|
+
Literal,
|
|
13
|
+
Optional,
|
|
14
|
+
Set,
|
|
10
15
|
Text,
|
|
11
16
|
Tuple,
|
|
12
|
-
Dict,
|
|
13
17
|
Type,
|
|
14
|
-
Any,
|
|
15
|
-
Set,
|
|
16
|
-
Union,
|
|
17
18
|
TypeVar,
|
|
18
|
-
|
|
19
|
-
Literal,
|
|
19
|
+
Union,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
import structlog
|
|
@@ -60,8 +60,10 @@ from rasa.shared.constants import (
|
|
|
60
60
|
)
|
|
61
61
|
from rasa.shared.core.constants import ACTION_RESET_ROUTING, ACTION_TRIGGER_CHITCHAT
|
|
62
62
|
from rasa.shared.core.domain import Domain
|
|
63
|
-
from rasa.shared.core.flows import
|
|
63
|
+
from rasa.shared.core.flows import Flow, FlowsList
|
|
64
|
+
from rasa.shared.core.policies.utils import contains_intentless_policy_responses
|
|
64
65
|
from rasa.shared.core.slots import Slot
|
|
66
|
+
from rasa.shared.core.training_data.structures import StoryGraph
|
|
65
67
|
from rasa.shared.exceptions import RasaException
|
|
66
68
|
from rasa.shared.nlu.training_data.message import Message
|
|
67
69
|
|
|
@@ -621,11 +623,18 @@ def _recursively_check_required_components(
|
|
|
621
623
|
|
|
622
624
|
|
|
623
625
|
def validate_flow_component_dependencies(
|
|
624
|
-
flows: FlowsList,
|
|
626
|
+
flows: FlowsList,
|
|
627
|
+
domain: Domain,
|
|
628
|
+
story_graph: StoryGraph,
|
|
629
|
+
model_configuration: GraphModelConfiguration,
|
|
625
630
|
) -> None:
|
|
626
631
|
if (pattern_chitchat := flows.flow_by_id(FLOW_PATTERN_CHITCHAT)) is not None:
|
|
627
632
|
_validate_chitchat_dependencies(pattern_chitchat, model_configuration)
|
|
628
633
|
|
|
634
|
+
_validate_intentless_policy_responses(
|
|
635
|
+
flows, domain, story_graph, model_configuration
|
|
636
|
+
)
|
|
637
|
+
|
|
629
638
|
|
|
630
639
|
def _validate_chitchat_dependencies(
|
|
631
640
|
pattern_chitchat: Flow, model_configuration: GraphModelConfiguration
|
|
@@ -653,6 +662,32 @@ def _validate_chitchat_dependencies(
|
|
|
653
662
|
)
|
|
654
663
|
|
|
655
664
|
|
|
665
|
+
def _validate_intentless_policy_responses(
|
|
666
|
+
flows: FlowsList,
|
|
667
|
+
domain: Domain,
|
|
668
|
+
story_graph: StoryGraph,
|
|
669
|
+
model_configuration: GraphModelConfiguration,
|
|
670
|
+
) -> None:
|
|
671
|
+
"""If IntentlessPolicy is configured, validate that it has responses to use:
|
|
672
|
+
either responses from the domain that are not part of any flow, or from
|
|
673
|
+
end-to-end stories.
|
|
674
|
+
"""
|
|
675
|
+
if not model_configuration.predict_schema.has_node(IntentlessPolicy):
|
|
676
|
+
return
|
|
677
|
+
|
|
678
|
+
if not contains_intentless_policy_responses(flows, domain, story_graph):
|
|
679
|
+
structlogger.error(
|
|
680
|
+
"validation.intentless_policy.no_applicable_responses_found",
|
|
681
|
+
event_info=(
|
|
682
|
+
"IntentlessPolicy is configured, but no applicable responses are "
|
|
683
|
+
"found. Please make sure that there are responses defined in the "
|
|
684
|
+
"domain that are not part of any flow, or that there are "
|
|
685
|
+
"end-to-end stories in the training data."
|
|
686
|
+
),
|
|
687
|
+
)
|
|
688
|
+
sys.exit(1)
|
|
689
|
+
|
|
690
|
+
|
|
656
691
|
def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
|
|
657
692
|
"""Extracts the index of a component of the given class in the schema.
|
|
658
693
|
This function assumes that each component's node name is stored in a way
|
rasa/model_training.py
CHANGED
|
@@ -302,6 +302,7 @@ async def _train_graph(
|
|
|
302
302
|
)
|
|
303
303
|
flows = file_importer.get_flows()
|
|
304
304
|
domain = file_importer.get_domain()
|
|
305
|
+
story_graph = file_importer.get_stories()
|
|
305
306
|
model_configuration = recipe.graph_config_for_recipe(
|
|
306
307
|
config,
|
|
307
308
|
kwargs,
|
|
@@ -314,7 +315,7 @@ async def _train_graph(
|
|
|
314
315
|
)
|
|
315
316
|
rasa.engine.validation.validate_model_client_configuration_setup(config)
|
|
316
317
|
rasa.engine.validation.validate_flow_component_dependencies(
|
|
317
|
-
flows, model_configuration
|
|
318
|
+
flows, domain, story_graph, model_configuration
|
|
318
319
|
)
|
|
319
320
|
rasa.engine.validation.validate_command_generator_setup(model_configuration)
|
|
320
321
|
|
rasa/shared/constants.py
CHANGED
|
@@ -97,6 +97,8 @@ UTTER_ASK_PREFIX = "utter_ask_"
|
|
|
97
97
|
ACTION_ASK_PREFIX = "action_ask_"
|
|
98
98
|
FLOW_PREFIX = "flow_"
|
|
99
99
|
|
|
100
|
+
UTTER_FREE_CHITCHAT_RESPONSE = "utter_free_chitchat_response"
|
|
101
|
+
|
|
100
102
|
ASSISTANT_ID_KEY = "assistant_id"
|
|
101
103
|
ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
|
|
102
104
|
|
|
@@ -115,6 +117,7 @@ CONFIG_MANDATORY_KEYS_NLU = ["language"] + CONFIG_MANDATORY_COMMON_KEYS
|
|
|
115
117
|
CONFIG_MANDATORY_KEYS = list(
|
|
116
118
|
set(CONFIG_MANDATORY_KEYS_CORE + CONFIG_MANDATORY_KEYS_NLU)
|
|
117
119
|
)
|
|
120
|
+
CONFIG_RECIPE_KEY = "recipe"
|
|
118
121
|
|
|
119
122
|
# Keys related to Forms (in the Domain)
|
|
120
123
|
REQUIRED_SLOTS_KEY = "required_slots"
|
rasa/shared/core/domain.py
CHANGED
|
@@ -1651,6 +1651,14 @@ class Domain:
|
|
|
1651
1651
|
"""Write domain to a file."""
|
|
1652
1652
|
as_yaml = self.as_yaml()
|
|
1653
1653
|
rasa.shared.utils.io.write_text_file(as_yaml, filename)
|
|
1654
|
+
# run the check again on the written domain to catch any errors
|
|
1655
|
+
# that may have been missed in the user defined domain files
|
|
1656
|
+
structlogger.info(
|
|
1657
|
+
"domain.persist.domain_written_to_file",
|
|
1658
|
+
event_info="The entire domain content has been written to file.",
|
|
1659
|
+
filename=filename,
|
|
1660
|
+
)
|
|
1661
|
+
Domain.is_domain_file(filename)
|
|
1654
1662
|
|
|
1655
1663
|
def as_yaml(self) -> Text:
|
|
1656
1664
|
"""Dump the `Domain` object as a YAML string.
|
|
@@ -1945,17 +1953,18 @@ class Domain:
|
|
|
1945
1953
|
|
|
1946
1954
|
try:
|
|
1947
1955
|
content = read_yaml_file(filename)
|
|
1948
|
-
except (RasaException, YamlSyntaxException):
|
|
1949
|
-
structlogger.
|
|
1956
|
+
except (RasaException, YamlSyntaxException) as error:
|
|
1957
|
+
structlogger.error(
|
|
1950
1958
|
"domain.cannot_load_domain_file",
|
|
1951
1959
|
file=filename,
|
|
1960
|
+
error=error,
|
|
1952
1961
|
event_info=(
|
|
1953
1962
|
f"The file {filename} could not be loaded as domain file. "
|
|
1954
1963
|
f"You can use https://yamlchecker.com/ to validate "
|
|
1955
1964
|
f"the YAML syntax of your file."
|
|
1956
1965
|
),
|
|
1957
1966
|
)
|
|
1958
|
-
|
|
1967
|
+
raise RasaException(f"Domain could not be loaded: {error}")
|
|
1959
1968
|
|
|
1960
1969
|
return any(key in content for key in ALL_DOMAIN_KEYS)
|
|
1961
1970
|
|
|
File without changes
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import Set, Text
|
|
2
|
+
|
|
3
|
+
from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
4
|
+
from rasa.graph_components.providers.forms_provider import Forms
|
|
5
|
+
from rasa.graph_components.providers.responses_provider import Responses
|
|
6
|
+
from rasa.shared.constants import (
|
|
7
|
+
REQUIRED_SLOTS_KEY,
|
|
8
|
+
UTTER_ASK_PREFIX,
|
|
9
|
+
UTTER_FREE_CHITCHAT_RESPONSE,
|
|
10
|
+
)
|
|
11
|
+
from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT
|
|
12
|
+
from rasa.shared.core.domain import Domain
|
|
13
|
+
from rasa.shared.core.flows import FlowsList
|
|
14
|
+
from rasa.shared.core.training_data.structures import StoryGraph
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def collect_form_responses(forms: Forms) -> Set[Text]:
|
|
18
|
+
"""Collect responses that belong the requested slots in forms.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
forms: the forms from the domain
|
|
22
|
+
Returns:
|
|
23
|
+
all utterances used in forms
|
|
24
|
+
"""
|
|
25
|
+
form_responses = set()
|
|
26
|
+
for _, form_info in forms.data.items():
|
|
27
|
+
for required_slot in form_info.get(REQUIRED_SLOTS_KEY, []):
|
|
28
|
+
form_responses.add(f"{UTTER_ASK_PREFIX}{required_slot}")
|
|
29
|
+
return form_responses
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def filter_responses_for_intentless_policy(
|
|
33
|
+
responses: Responses, forms: Forms, flows: FlowsList
|
|
34
|
+
) -> Responses:
|
|
35
|
+
"""Filters out responses that are unwanted for the intentless policy.
|
|
36
|
+
|
|
37
|
+
This includes utterances used in flows and forms.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
responses: the responses from the domain
|
|
41
|
+
forms: the forms from the domain
|
|
42
|
+
flows: all flows
|
|
43
|
+
Returns:
|
|
44
|
+
The remaining, relevant responses for the intentless policy.
|
|
45
|
+
"""
|
|
46
|
+
form_responses = collect_form_responses(forms)
|
|
47
|
+
flow_responses = flows.utterances
|
|
48
|
+
combined_responses = form_responses | flow_responses
|
|
49
|
+
filtered_responses = {
|
|
50
|
+
name: variants
|
|
51
|
+
for name, variants in responses.data.items()
|
|
52
|
+
if name not in combined_responses
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pattern_chitchat = flows.flow_by_id(FLOW_PATTERN_CHITCHAT)
|
|
56
|
+
|
|
57
|
+
# The following condition is highly unlikely, but mypy requires the case
|
|
58
|
+
# of pattern_chitchat == None to be addressed
|
|
59
|
+
if not pattern_chitchat:
|
|
60
|
+
return Responses(data=filtered_responses)
|
|
61
|
+
|
|
62
|
+
# if action_trigger_chitchat, filter out "utter_free_chitchat_response"
|
|
63
|
+
has_action_trigger_chitchat = pattern_chitchat.has_action_step(
|
|
64
|
+
ACTION_TRIGGER_CHITCHAT
|
|
65
|
+
)
|
|
66
|
+
if has_action_trigger_chitchat:
|
|
67
|
+
filtered_responses.pop(UTTER_FREE_CHITCHAT_RESPONSE, None)
|
|
68
|
+
|
|
69
|
+
return Responses(data=filtered_responses)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def contains_intentless_policy_responses(
|
|
73
|
+
flows: FlowsList, domain: Domain, story_graph: StoryGraph
|
|
74
|
+
) -> bool:
|
|
75
|
+
"""Checks if IntentlessPolicy has applicable responses: either responses in the
|
|
76
|
+
domain that are not part of any flow, or if there are e2e stories.
|
|
77
|
+
"""
|
|
78
|
+
responses = filter_responses_for_intentless_policy(
|
|
79
|
+
Responses(data=domain.responses), Forms(data=domain.forms), flows
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
has_applicable_responses = bool(
|
|
83
|
+
responses and responses.data and len(responses.data) > 0
|
|
84
|
+
)
|
|
85
|
+
has_e2e_stories = bool(story_graph and story_graph.has_e2e_stories())
|
|
86
|
+
|
|
87
|
+
return has_applicable_responses or has_e2e_stories
|
|
@@ -376,6 +376,7 @@ def extract_attrs_for_execute_commands(
|
|
|
376
376
|
all_flows: FlowsList,
|
|
377
377
|
execution_context: ExecutionContext,
|
|
378
378
|
story_graph: Optional[StoryGraph] = None,
|
|
379
|
+
domain: Optional[Domain] = None,
|
|
379
380
|
) -> Dict[str, Any]:
|
|
380
381
|
return {
|
|
381
382
|
"number_of_events": len(tracker.events),
|
|
@@ -419,6 +420,7 @@ def extract_attrs_for_clean_up_commands(
|
|
|
419
420
|
all_flows: FlowsList,
|
|
420
421
|
execution_context: ExecutionContext,
|
|
421
422
|
story_graph: Optional[StoryGraph] = None,
|
|
423
|
+
domain: Optional[Domain] = None,
|
|
422
424
|
) -> Dict[str, Any]:
|
|
423
425
|
commands_list = []
|
|
424
426
|
|
rasa/version.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: rasa-pro
|
|
3
|
-
Version: 3.10.
|
|
3
|
+
Version: 3.10.20
|
|
4
4
|
Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
|
|
5
|
-
Home-page: https://rasa.com
|
|
6
5
|
Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
|
|
7
6
|
Author: Rasa Technologies GmbH
|
|
8
7
|
Author-email: hi@rasa.com
|
|
@@ -61,13 +60,13 @@ Requires-Dist: jsonschema (>=4.22)
|
|
|
61
60
|
Requires-Dist: keras (==2.14.0)
|
|
62
61
|
Requires-Dist: langchain (>=0.2.17,<0.3.0)
|
|
63
62
|
Requires-Dist: langchain-community (>=0.2.19,<0.3.0)
|
|
64
|
-
Requires-Dist: litellm (>=1.
|
|
63
|
+
Requires-Dist: litellm (>=1.64.1,<1.65.0)
|
|
65
64
|
Requires-Dist: matplotlib (>=3.7,<3.8)
|
|
66
65
|
Requires-Dist: mattermostwrapper (>=2.2,<2.3)
|
|
67
66
|
Requires-Dist: mlflow (>=2.15.1,<3.0.0) ; extra == "mlflow"
|
|
68
67
|
Requires-Dist: networkx (>=3.1,<3.2)
|
|
69
68
|
Requires-Dist: numpy (>=1.23.5,<1.25.0) ; python_version >= "3.9" and python_version < "3.11"
|
|
70
|
-
Requires-Dist: openai (>=1.
|
|
69
|
+
Requires-Dist: openai (>=1.68.2,<1.69.0)
|
|
71
70
|
Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
|
|
72
71
|
Requires-Dist: opentelemetry-api (>=1.16.0,<1.17.0)
|
|
73
72
|
Requires-Dist: opentelemetry-exporter-jaeger (>=1.16.0,<1.17.0)
|
|
@@ -84,7 +83,6 @@ Requires-Dist: protobuf (>=4.23.3,<4.25.4)
|
|
|
84
83
|
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
85
84
|
Requires-Dist: psycopg2-binary (>=2.9.9,<2.10.0)
|
|
86
85
|
Requires-Dist: pycountry (>=22.3.5,<23.0.0)
|
|
87
|
-
Requires-Dist: pydantic (>=2.0,<3.0)
|
|
88
86
|
Requires-Dist: pydot (>=1.4,<1.5)
|
|
89
87
|
Requires-Dist: pykwalify (>=1.8,<1.9)
|
|
90
88
|
Requires-Dist: pymilvus (>=2.4.0,<2.4.2)
|
|
@@ -133,7 +131,7 @@ Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "darwin"
|
|
|
133
131
|
Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "linux"
|
|
134
132
|
Requires-Dist: tensorflow-macos (==2.14.1) ; sys_platform == "darwin" and platform_machine == "arm64"
|
|
135
133
|
Requires-Dist: tensorflow-metal (==1.1.0) ; (sys_platform == "darwin" and platform_machine == "arm64") and (extra == "metal")
|
|
136
|
-
Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and
|
|
134
|
+
Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and platform_machine != "arm64" and platform_machine != "aarch64"
|
|
137
135
|
Requires-Dist: tensorflow_hub (>=0.13.0,<0.14.0)
|
|
138
136
|
Requires-Dist: terminaltables (>=3.1.10,<3.2.0)
|
|
139
137
|
Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
|
|
@@ -148,6 +146,7 @@ Requires-Dist: webexteamssdk (>=1.6.1,<1.7.0)
|
|
|
148
146
|
Requires-Dist: websockets (>=10.4,<11.0)
|
|
149
147
|
Requires-Dist: wheel (>=0.40.0)
|
|
150
148
|
Project-URL: Documentation, https://rasa.com/docs
|
|
149
|
+
Project-URL: Homepage, https://rasa.com
|
|
151
150
|
Project-URL: Repository, https://github.com/rasahq/rasa
|
|
152
151
|
Description-Content-Type: text/markdown
|
|
153
152
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
README.md,sha256=hu3oA1lnwNcUZbeb3AlbNJidVy64MCYzXIqai8rPORY,3298
|
|
2
1
|
rasa/__init__.py,sha256=YXG8RzVxiSJ__v-AewtV453YoCbmzWlHsU_4S0O2XpE,206
|
|
3
2
|
rasa/__main__.py,sha256=s0wac5PWbCVu7lJyKUCLylKvE-K7UA6QzVfKUY-46-g,5825
|
|
4
3
|
rasa/anonymization/__init__.py,sha256=Z-ZUW2ofZGfI6ysjYIS7U0JL4JSzDNOkHiiXK488Zik,86
|
|
@@ -75,7 +74,7 @@ rasa/cli/project_templates/tutorial/data/flows.yml,sha256=9C23uQYm_JVguQJ7u51U4k
|
|
|
75
74
|
rasa/cli/project_templates/tutorial/data/patterns.yml,sha256=rIO8yjg6QU_l35pjQKFaqsOLpaWDMv4q1FS5O7VCV1Q,304
|
|
76
75
|
rasa/cli/project_templates/tutorial/domain.yml,sha256=DFnifO_0cD6PYKMsF011FoIDN_spaWbnuR7mhsF7dNk,402
|
|
77
76
|
rasa/cli/project_templates/tutorial/endpoints.yml,sha256=Mmjm5KDuyL_46dIe0issP8MKNzESYWU0JyYPWPVlWFw,1479
|
|
78
|
-
rasa/cli/run.py,sha256=
|
|
77
|
+
rasa/cli/run.py,sha256=tIizWzSwEt0fc7w1EpUcJtvLnIiYwzr-dr9l3kyhJ0c,4354
|
|
79
78
|
rasa/cli/scaffold.py,sha256=Eqv44T7b5cOd2FKLU1tSrAVPKwMfoiUIjc43PtaxJGg,7988
|
|
80
79
|
rasa/cli/shell.py,sha256=wymYOj6jdUON0y7pe-rpRqarWDGaDquU7PRp8knxqHk,4264
|
|
81
80
|
rasa/cli/studio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -86,7 +85,7 @@ rasa/cli/studio/upload.py,sha256=kdHqrVGsEbbqH5fz_HusWwJEycB31SHaPlXer8lXAE0,206
|
|
|
86
85
|
rasa/cli/telemetry.py,sha256=ZywhlOpp0l2Yz9oEcOGA2ej3SEkSTisKPpBhn_fS7tc,3538
|
|
87
86
|
rasa/cli/test.py,sha256=Ub7Cm9rFQ_tkB310jPYzVwU0Di88Z7IE0nLi1o-aYbA,8901
|
|
88
87
|
rasa/cli/train.py,sha256=_fQi7Sx15LGDyJDV20FJJ2oDZoPGHBfV8xf2t5Kzkpk,10298
|
|
89
|
-
rasa/cli/utils.py,sha256=
|
|
88
|
+
rasa/cli/utils.py,sha256=r1zxiGSPzSkvyrxzB1PxLiDIoADqwWXykONs7e9xpy8,15891
|
|
90
89
|
rasa/cli/visualize.py,sha256=YmRAATAfxHpgE8_PknGyM-oIujwICNzVftTzz6iLNNc,1256
|
|
91
90
|
rasa/cli/x.py,sha256=qJtNheYwdxxwZl-M2KcEbCk8lzWVGMfI6em-5-Xj05w,6825
|
|
92
91
|
rasa/constants.py,sha256=XZYjc2dDN2q3ixchLfRRNGAqxD2uL5-z_ZYoqJwLgxM,1309
|
|
@@ -117,10 +116,10 @@ rasa/core/brokers/kafka.py,sha256=GYjwaitE0K4OMXTWVJ_qI5NdsDZfESqF8Ba2oP7tcjQ,13
|
|
|
117
116
|
rasa/core/brokers/pika.py,sha256=r-xmaBv92eMV5N6PxtykwrRmlvmq304gX5aFiwq1dZQ,14363
|
|
118
117
|
rasa/core/brokers/sql.py,sha256=4cDqpbwXwjcq5THbrgRptfUq38-UOnckZq7S7d9wU9o,2728
|
|
119
118
|
rasa/core/channels/__init__.py,sha256=zXFLOIIbArflZ4bwo6Dnaj-_IY-BAEPnsRcpnxJyeF4,2006
|
|
120
|
-
rasa/core/channels/audiocodes.py,sha256=
|
|
119
|
+
rasa/core/channels/audiocodes.py,sha256=v3Sl6lTS6Ig6EyIQSpvj5pQAh3PXE1Y2l0pL7HfgF7s,17543
|
|
121
120
|
rasa/core/channels/botframework.py,sha256=xyc_n7DJ3uglqvkr0IrQ3xxPWgvaqSOLHWx9BUS0enE,11668
|
|
122
121
|
rasa/core/channels/callback.py,sha256=4LpjtJgQMAAXHwZrcVlVEUdpDTRqTe6n7XtwCusa75U,2750
|
|
123
|
-
rasa/core/channels/channel.py,sha256=
|
|
122
|
+
rasa/core/channels/channel.py,sha256=MRfoQXFQ3eGDA-6EEnGj3ii8PIj-DNb7rfUJKDn2v8g,17736
|
|
124
123
|
rasa/core/channels/console.py,sha256=fYhkSY8a_pn09ssjTczsKTALinABogpFJzzWTnL7MP8,8076
|
|
125
124
|
rasa/core/channels/development_inspector.py,sha256=oh2zrIEyQOl-HTKfwZmnMvJ6RZkhbqQrLeEEW0FX14k,2982
|
|
126
125
|
rasa/core/channels/facebook.py,sha256=ub8DCnTPe3_EyYtdYE49mo2Y-UNpURj6Qx9590oadeM,15816
|
|
@@ -260,7 +259,7 @@ rasa/core/channels/slack.py,sha256=3b8OZQ_gih5XBwhQ1q4BbBUC1SCAPaO9AoJEn2NaoQE,2
|
|
|
260
259
|
rasa/core/channels/socketio.py,sha256=k0b6aWE8gqhXBaLN7Sa5qaxqrWEFqf95ZeN-fX9bhPA,10675
|
|
261
260
|
rasa/core/channels/telegram.py,sha256=XvzU7KAgjmRcu2vUJ-5L2eYAAuYBqtcYlhq1Jo6kLns,10649
|
|
262
261
|
rasa/core/channels/twilio.py,sha256=c63uFLVKaK4Fj8MAn9BSQtxiV_Ezq4POezHo8zWIoiw,5938
|
|
263
|
-
rasa/core/channels/twilio_voice.py,sha256=
|
|
262
|
+
rasa/core/channels/twilio_voice.py,sha256=YOvm2jNaHGGPlhNZqf_9T9IHu7Ibp0FfuqGS0voTRL0,15007
|
|
264
263
|
rasa/core/channels/vier_cvg.py,sha256=PfvSluQqgJbP0JzZPFUvum3z7H55JPPeobcD-z5zCkw,13544
|
|
265
264
|
rasa/core/channels/voice_aware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
266
265
|
rasa/core/channels/voice_aware/jambonz.py,sha256=aMXK2bGXioupVUUKZpkeYiAprilvVc2xEDBytRIcdMs,3481
|
|
@@ -308,7 +307,7 @@ rasa/core/policies/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
308
307
|
rasa/core/policies/flows/flow_exceptions.py,sha256=_FQuN-cerQDM1pivce9bz4zylh5UYkljvYS1gjDukHI,1527
|
|
309
308
|
rasa/core/policies/flows/flow_executor.py,sha256=DNO_kUdisI93XIY9-QtYpqCp7faxEpkIqhcfFLkaets,25690
|
|
310
309
|
rasa/core/policies/flows/flow_step_result.py,sha256=agjPrD6lahGSe2ViO5peBeoMdI9ngVGRSgtytgxmJmg,1360
|
|
311
|
-
rasa/core/policies/intentless_policy.py,sha256=
|
|
310
|
+
rasa/core/policies/intentless_policy.py,sha256=zwHzcPM2JM0fPo_ywcQWwNkrwwcjLsdRQDc0PdtFn8A,33708
|
|
312
311
|
rasa/core/policies/intentless_prompt_template.jinja2,sha256=KhIL3cruMmkxhrs5oVbqgSvK6ZiN_6TQ_jXrgtEB-ZY,677
|
|
313
312
|
rasa/core/policies/memoization.py,sha256=XoRxUdYUGRfO47tAEyc5k5pUgt38a4fipO336EU5Vdc,19466
|
|
314
313
|
rasa/core/policies/policy.py,sha256=HeVtIaV0dA1QcAG3vjdn-4g7-oUEJPL4u01ETJt78YA,27464
|
|
@@ -371,7 +370,7 @@ rasa/dialogue_understanding/generator/multi_step/__init__.py,sha256=47DEQpj8HBSa
|
|
|
371
370
|
rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2,sha256=Y0m673tAML3cFPaLM-urMXDsBYUUcXIw9YUpkAhGUuA,2933
|
|
372
371
|
rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2,sha256=8l93_QBKBYnqLICVdiTu5ejZDE8F36BU8-qwba0px44,1927
|
|
373
372
|
rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py,sha256=Gvnr1hcrwF_4vvHsvIH5Au0S2g1-RxSirvhQuXXZIFE,31864
|
|
374
|
-
rasa/dialogue_understanding/generator/nlu_command_adapter.py,sha256=
|
|
373
|
+
rasa/dialogue_understanding/generator/nlu_command_adapter.py,sha256=wEqoSVUtr00lhbE9L9WqKfZkMKOvm7UGe_E5aqXgn6I,9210
|
|
375
374
|
rasa/dialogue_understanding/generator/single_step/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
376
375
|
rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2,sha256=qVTuas5XgAv2M_hsihyXl-wAnBDEpg_uhVvNrR5m-h0,3751
|
|
377
376
|
rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py,sha256=fSvfcFAOh9g6Vh_vmO1RPAi5sYDgLMeVE084qfod8QA,16329
|
|
@@ -393,8 +392,8 @@ rasa/dialogue_understanding/patterns/search.py,sha256=X7HaMyFwS8gPprKFSOJvCoC6Ng
|
|
|
393
392
|
rasa/dialogue_understanding/patterns/session_start.py,sha256=yglhIEkkquRf0YppZ4Cuv2eHlA5qscGoVXr0d-2bV-E,1153
|
|
394
393
|
rasa/dialogue_understanding/patterns/skip_question.py,sha256=rvZuVUxulikwUhP01MAIgkcHZ4Si7mzxNedH6QBPdX4,1214
|
|
395
394
|
rasa/dialogue_understanding/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
396
|
-
rasa/dialogue_understanding/processor/command_processor.py,sha256=
|
|
397
|
-
rasa/dialogue_understanding/processor/command_processor_component.py,sha256=
|
|
395
|
+
rasa/dialogue_understanding/processor/command_processor.py,sha256=OEJ8uwV9LsaRN8Jw0IF9GpF-Gh0P8SaW_SDh5ELb7zk,25510
|
|
396
|
+
rasa/dialogue_understanding/processor/command_processor_component.py,sha256=xpHTGfZQ2RHm7s1mfM9RLGyADzNosUde0edECMwmDuc,1606
|
|
398
397
|
rasa/dialogue_understanding/stack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
399
398
|
rasa/dialogue_understanding/stack/dialogue_stack.py,sha256=j8MnLCyv6cAZVpKRaUVM-Z5HqgWP-scrnaiQXzLNBwY,5243
|
|
400
399
|
rasa/dialogue_understanding/stack/frames/__init__.py,sha256=CXLs8I_eeJ-d2tQmS19V26OM6CHy3VN5whH5uHBodj4,656
|
|
@@ -423,7 +422,7 @@ rasa/e2e_test/stub_custom_action.py,sha256=teq8c5I6IuUsFX4lPdeBLY3j0SLSMCC95KmKx
|
|
|
423
422
|
rasa/e2e_test/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
424
423
|
rasa/e2e_test/utils/e2e_yaml_utils.py,sha256=XvP14DGHMfsNXyI7uTV-GTAdqv-r5FNmpFmvEIn93OM,1601
|
|
425
424
|
rasa/e2e_test/utils/io.py,sha256=HVsFb8uVPTlu7PcQdFmMNUFf0rRrD5Wiys0oMZqu2nA,19016
|
|
426
|
-
rasa/e2e_test/utils/validation.py,sha256=
|
|
425
|
+
rasa/e2e_test/utils/validation.py,sha256=k4zlwAMX6O45fyHFKqBXsBpeThpEVrQoj9B357AXJ7U,2336
|
|
427
426
|
rasa/engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
428
427
|
rasa/engine/caching.py,sha256=Uu-0yn_eQGysmW7nsub-tb3gD8QNz6TNssNd-GIthuI,16451
|
|
429
428
|
rasa/engine/constants.py,sha256=w7hyRd2gU8JJyECqGG1meIS3volOCD3lYpVuzDLGz-s,623
|
|
@@ -448,7 +447,7 @@ rasa/engine/training/components.py,sha256=ZOSTbPEHth545q41B9geXKdEtIYZ3PaZdwSXrA
|
|
|
448
447
|
rasa/engine/training/fingerprinting.py,sha256=lY4wHte37470MR6sBaERt0WT9NF06NUGTX9bRAh-W_4,2006
|
|
449
448
|
rasa/engine/training/graph_trainer.py,sha256=fCnFZAv7UNxFjaLRY0MxPd18d3mO9It4Uk1Joq7Q3Mc,10636
|
|
450
449
|
rasa/engine/training/hooks.py,sha256=u7HQXDJJT4pBzQUaIIfuM3YEreGjRdp0IEv6XUrRFtk,5469
|
|
451
|
-
rasa/engine/validation.py,sha256=
|
|
450
|
+
rasa/engine/validation.py,sha256=Gk_OA9H5qu6oEmn6lXVizzQCynNI0aXoxXy1YpWNExU,37823
|
|
452
451
|
rasa/env.py,sha256=zLzQMkATVIZj6s4C7RsLLOLT8g6-Q96m5iBaHW_mEA8,480
|
|
453
452
|
rasa/exceptions.py,sha256=acZiGDb5zC1ZGv1oBPHImBeRKxyHOA_mW6N8e9nOEaU,2116
|
|
454
453
|
rasa/graph_components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -469,7 +468,6 @@ rasa/graph_components/validators/default_recipe_validator.py,sha256=BHrF6NTfJz42
|
|
|
469
468
|
rasa/graph_components/validators/finetuning_validator.py,sha256=38AcwmV8cF5TIlWhUIzh98wtZf934ix04HcczCJiWkU,12863
|
|
470
469
|
rasa/hooks.py,sha256=3nsfCA142V56mBQ7ktBXhD_RyaSrfj7fY3t7HnsD4Pc,3709
|
|
471
470
|
rasa/jupyter.py,sha256=x_GF9PK2zMhltb48GEIV9YZ4pRhCto8nV5SioYSCljI,1782
|
|
472
|
-
rasa/keys,sha256=2Stg1fstgJ203cOoW1B2gGMY29fhEnjIfTVxKv_fqPo,101
|
|
473
471
|
rasa/llm_fine_tuning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
474
472
|
rasa/llm_fine_tuning/annotation_module.py,sha256=wFmW3d6lI5o49OWmdbYQlgr24rqHDgA0T0hLM1pSb9U,8578
|
|
475
473
|
rasa/llm_fine_tuning/conversations.py,sha256=iW2hoR23Km5wnMC7t8pOXH2Zj3LVcA62xrx2aKDRP78,5208
|
|
@@ -490,7 +488,7 @@ rasa/markers/upload.py,sha256=Ot1s_O-CEIB9c4CKUlfOldiJo92pdqxFUHOPCU7E_NU,2518
|
|
|
490
488
|
rasa/markers/validate.py,sha256=YypXKRS87xxrMMEz9HpAQzYJUwg0OPbczMXBRNjlJq4,709
|
|
491
489
|
rasa/model.py,sha256=GH1-N6Po3gL3nwfa9eGoN2bMRNMrn4f3mi17-osW3T0,3491
|
|
492
490
|
rasa/model_testing.py,sha256=h0QUpJu6p_TDse3aHjCfYwI6OGH47b3Iuo5Ot0HQADM,14959
|
|
493
|
-
rasa/model_training.py,sha256=
|
|
491
|
+
rasa/model_training.py,sha256=Z7Rn0RyMNduLtIDbP1r6bgj6nZRUuOuhxLZ4M9dzSg8,20775
|
|
494
492
|
rasa/nlu/__init__.py,sha256=D0IYuTK_ZQ_F_9xsy0bXxVCAtU62Fzvp8S7J9tmfI_c,123
|
|
495
493
|
rasa/nlu/classifiers/__init__.py,sha256=Qvrf7_rfiMxm2Vt2fClb56R3QFExf7WPdFdL-AOvgsk,118
|
|
496
494
|
rasa/nlu/classifiers/classifier.py,sha256=9fm1mORuFf1vowYIXmqE9yLRKdSC4nGQW7UqNZQipKY,133
|
|
@@ -553,12 +551,12 @@ rasa/nlu/utils/spacy_utils.py,sha256=pBvsCVKVuZ3b2Pjn-XuOVZ6lzZu9Voc2R4N1VczwtCM
|
|
|
553
551
|
rasa/plugin.py,sha256=H_OZcHy_U3eAK-JHr43TSxcPqS0JEGcZkFvmumeeJEs,2670
|
|
554
552
|
rasa/server.py,sha256=pUdhi5dkhzEj4bngj2bTUKJohepjpY-aZ4MGKHYZRH0,57775
|
|
555
553
|
rasa/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
556
|
-
rasa/shared/constants.py,sha256=
|
|
554
|
+
rasa/shared/constants.py,sha256=_p9q5FymIxXwuypT8DXLxxna0tD2ztYunvUDrD7Ct8A,9514
|
|
557
555
|
rasa/shared/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
558
556
|
rasa/shared/core/command_payload_reader.py,sha256=Vhiop9LWFawaEruRifBBrVmoEJ-fj1Tli1wBvsYu2_I,3563
|
|
559
557
|
rasa/shared/core/constants.py,sha256=6xnows8KdTMIkPA8SMj9xdAPAkFE_dQcJlcVB4NIPPQ,5200
|
|
560
558
|
rasa/shared/core/conversation.py,sha256=tw1fD2XB3gOdQjDI8hHo5TAAmE2JYNogQGWe3rE929w,1385
|
|
561
|
-
rasa/shared/core/domain.py,sha256=
|
|
559
|
+
rasa/shared/core/domain.py,sha256=_oemCcMY1SZgSrH-Yl9qv9n2vGNNDwdxlBxK3GZQaZQ,80517
|
|
562
560
|
rasa/shared/core/events.py,sha256=38o-Zz3uQSKrYVfKw_Xr-EBvSusyXy3rQAvN25QzQJk,84875
|
|
563
561
|
rasa/shared/core/flows/__init__.py,sha256=HszhIvEARpmyxABFc1MKYvj8oy04WiZW1xmCdToakbs,181
|
|
564
562
|
rasa/shared/core/flows/flow.py,sha256=C8TxzxxEtZVrEMLUY57BNA8rEIwcYZaLtJ6pPYeBMRI,21242
|
|
@@ -584,6 +582,8 @@ rasa/shared/core/flows/steps/start.py,sha256=AJpKIm0S3GZYLEs3ybXW0Zrq03Pu9lvirNa
|
|
|
584
582
|
rasa/shared/core/flows/validation.py,sha256=OnSXfWp5S_IMAUEvU_fN2bwAL5gi8PYZDA4PsOO4X7A,22935
|
|
585
583
|
rasa/shared/core/flows/yaml_flows_io.py,sha256=jaF5NgFAfaLUznZF57ZDvb0L9KdaE0cKBSJOZBKUXZQ,14804
|
|
586
584
|
rasa/shared/core/generator.py,sha256=y2B2Vn2xOl7k_smzefryoX048b_MTtSDqclx9Ompz9s,35687
|
|
585
|
+
rasa/shared/core/policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
586
|
+
rasa/shared/core/policies/utils.py,sha256=rWE_-48Ovc__V7wOKCJ-2lTerVRtN3iRHV4ZvuU2b2g,3070
|
|
587
587
|
rasa/shared/core/slot_mappings.py,sha256=3tNc8IETfgUZktV5iELT3dwFMHN1zCI35OlHAMqezEM,17854
|
|
588
588
|
rasa/shared/core/slots.py,sha256=oZmw5zCG4gA6W7AVPUSbhXC1vUXZrGDtx8YbTTITMTg,23675
|
|
589
589
|
rasa/shared/core/trackers.py,sha256=HOlmGPAuu89qKGQ7EPzrN1xIwYgik_SPjEeVJcVNMQc,42399
|
|
@@ -687,7 +687,7 @@ rasa/tracing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
687
687
|
rasa/tracing/config.py,sha256=O4iHkE4kF6r4uVAt3JUb--TniK7pWD4j3d08Vf_GuYY,12736
|
|
688
688
|
rasa/tracing/constants.py,sha256=N_MJLStE3IkmPKQCQv42epd3jdBMJ4Ith1dVO65N5ho,2425
|
|
689
689
|
rasa/tracing/instrumentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
690
|
-
rasa/tracing/instrumentation/attribute_extractors.py,sha256=
|
|
690
|
+
rasa/tracing/instrumentation/attribute_extractors.py,sha256=isqTG_fJxXH2GIKVPGeZMNFAeQJWzFKaks7e54GeEyo,23310
|
|
691
691
|
rasa/tracing/instrumentation/instrumentation.py,sha256=buoETr3rUHGirkaSY95SiTRqMZI1FCXjphcGXEH_e1A,45821
|
|
692
692
|
rasa/tracing/instrumentation/intentless_policy_instrumentation.py,sha256=8AdMOy_2mlKnlmt-muV8-eoT8jA52GXDzM0avejfg8A,4821
|
|
693
693
|
rasa/tracing/instrumentation/metrics.py,sha256=ByfKshoxNOqjKZwKTulqL71s5b3WugqLfjha3So0OEU,10534
|
|
@@ -727,9 +727,9 @@ rasa/utils/train_utils.py,sha256=f1NWpp5y6al0dzoQyyio4hc4Nf73DRoRSHDzEK6-C4E,212
|
|
|
727
727
|
rasa/utils/url_tools.py,sha256=JQcHL2aLqLHu82k7_d9imUoETCm2bmlHaDpOJ-dKqBc,1218
|
|
728
728
|
rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
|
|
729
729
|
rasa/validator.py,sha256=gGsuHZivo9MDGA8WCkvYEK5Payi2lpLpOi_PLGwg1Qk,63202
|
|
730
|
-
rasa/version.py,sha256=
|
|
731
|
-
rasa_pro-3.10.
|
|
732
|
-
rasa_pro-3.10.
|
|
733
|
-
rasa_pro-3.10.
|
|
734
|
-
rasa_pro-3.10.
|
|
735
|
-
rasa_pro-3.10.
|
|
730
|
+
rasa/version.py,sha256=3j2EOjZiqsty-50ZSw_uFUgdOT_Pkwi_bOhyuPMfbA4,118
|
|
731
|
+
rasa_pro-3.10.20.dist-info/METADATA,sha256=Hcsj2UTAbGpXeT34PtyH07P8yH_iMKg8BZPB3H1wiYY,10856
|
|
732
|
+
rasa_pro-3.10.20.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
|
|
733
|
+
rasa_pro-3.10.20.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
734
|
+
rasa_pro-3.10.20.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
|
|
735
|
+
rasa_pro-3.10.20.dist-info/RECORD,,
|
README.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<h1 align="center">Rasa Pro</h1>
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
|
|
5
|
-
[](https://github.com/RasaHQ/rasa-private/actions)
|
|
6
|
-
[](https://sonarcloud.io/summary/new_code?id=RasaHQ_rasa)
|
|
7
|
-
[](https://rasa.com/docs/rasa-pro/)
|
|
8
|
-
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
<hr />
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Rasa Pro is a framework for building scalable, dynamic conversational AI assistants that integrate large language models (LLMs) to enable more contextually aware and agentic interactions. Whether you’re new to conversational AI or an experienced developer, Rasa Pro offers enhanced flexibility, control, and performance for mission-critical applications.
|
|
15
|
-
|
|
16
|
-
Building on the foundation of Rasa Open Source, Rasa Pro adds advanced features like CALM (Conversational AI with Language Models) and Dialogue Understanding (DU), which enable developers to shift from traditional intent-driven systems to LLM-based agents. This allows for more robust, responsive interactions that adhere strictly to business logic, while reducing risks like prompt injection and minimizing hallucinations.
|
|
17
|
-
|
|
18
|
-
**Key Features:**
|
|
19
|
-
|
|
20
|
-
- **Flows for Business Logic:** Easily define business logic through Flows, a simplified way to describe how your AI assistant should handle conversations. Flows help streamline the development process, focusing on key tasks and reducing the complexity involved in managing conversations.
|
|
21
|
-
- **Automatic Conversation Repair:** Ensure seamless interactions by automatically handling interruptions or unexpected inputs. Developers have full control to customize these repairs based on specific use cases.
|
|
22
|
-
- **Customizable and Open:** Fully customizable code that allows developers to modify Rasa Pro to meet specific requirements, ensuring flexibility and adaptability to various conversational AI needs.
|
|
23
|
-
- **Robustness and Control:** Maintain strict adherence to business logic, preventing unwanted behaviors like prompt injection and hallucinations, leading to more reliable responses and secure interactions.
|
|
24
|
-
- **Built-in Security:** Safeguard sensitive data, control access, and ensure secure deployment, essential for production environments that demand high levels of security and compliance.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
A [free developer license](https://rasa.com/docs/rasa-pro/developer-edition/) is available so you can explore and get to know Rasa Pro. For small production deployments, the Extended Developer License allows you to take your assistant live in a limited capacity. A paid license is required for larger-scale production use, but all code is visible and can be customized as needed.
|
|
29
|
-
|
|
30
|
-
To get started right now, you can
|
|
31
|
-
|
|
32
|
-
`pip install rasa-pro`
|
|
33
|
-
|
|
34
|
-
Check out our
|
|
35
|
-
|
|
36
|
-
- [Rasa-pro Quickstart](https://rasa.com/docs/rasa-pro/installation/quickstart/),
|
|
37
|
-
- [Conversational AI with Language Models (CALM) conceptual rundown](https://rasa.com/docs/rasa-pro/calm/),
|
|
38
|
-
- [Rasa Pro / CALM tutorial](https://rasa.com/docs/rasa-pro/tutorial), and
|
|
39
|
-
- [Rasa pro changelog](https://rasa.com/docs/rasa/rasa-pro-changelog/)
|
|
40
|
-
|
|
41
|
-
for more. Also feel free to reach out to us on the [Rasa forum](https://forum.rasa.com/).
|
rasa/keys
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"segment": "CcvVD1I68Nkkxrv93cIqv1twIwrwG8nz", "sentry": "a283f1fde04347b099c8d729109dd450@o251570"}
|
|
File without changes
|
|
File without changes
|