rasa-pro 3.14.0rc1__py3-none-any.whl → 3.14.0rc3__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/agents/protocol/a2a/a2a_agent.py +50 -42
- rasa/agents/utils.py +27 -5
- rasa/agents/validation.py +7 -9
- rasa/api.py +1 -2
- rasa/builder/copilot/constants.py +4 -1
- rasa/builder/copilot/copilot.py +191 -79
- rasa/builder/copilot/models.py +306 -116
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +33 -12
- rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +59 -29
- rasa/builder/copilot/telemetry.py +8 -0
- rasa/builder/guardrails/policy_checker.py +1 -1
- rasa/builder/jobs.py +182 -12
- rasa/builder/models.py +12 -3
- rasa/builder/service.py +16 -2
- rasa/cli/dialogue_understanding_test.py +1 -0
- rasa/cli/e2e_test.py +1 -0
- rasa/cli/inspect.py +1 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/help.yml +8 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/human_handoff.yml +41 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/patterns.yml +32 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/show_faqs.yml +8 -0
- rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
- rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +2 -2
- rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +1 -2
- rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_not_slow.yml +33 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_slow.yml +47 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
- rasa/cli/run.py +1 -5
- rasa/cli/shell.py +1 -0
- rasa/cli/train.py +1 -0
- rasa/cli/validation/bot_config.py +7 -2
- rasa/core/available_agents.py +65 -55
- rasa/core/brokers/kafka.py +5 -1
- rasa/core/concurrent_lock_store.py +38 -21
- rasa/core/config/available_endpoints.py +0 -3
- rasa/core/config/configuration.py +36 -1
- rasa/core/constants.py +6 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +69 -4
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
- rasa/core/lock_store.py +4 -0
- rasa/core/policies/flows/agent_executor.py +16 -8
- rasa/core/redis_connection_factory.py +7 -2
- rasa/core/tracker_stores/redis_tracker_store.py +4 -0
- rasa/core/tracker_stores/sql_tracker_store.py +3 -1
- rasa/dialogue_understanding/commands/start_flow_command.py +10 -3
- rasa/dialogue_understanding/commands/utils.py +15 -4
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +4 -2
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +4 -4
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +4 -4
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +2 -2
- rasa/dialogue_understanding_test/du_test_runner.py +2 -2
- rasa/e2e_test/e2e_test_runner.py +2 -2
- rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +10 -4
- rasa/shared/agents/auth/constants.py +1 -0
- rasa/shared/core/flows/steps/call.py +2 -2
- rasa/telemetry.py +3 -3
- rasa/validator.py +37 -0
- rasa/version.py +1 -1
- {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/METADATA +14 -2
- {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/RECORD +83 -73
- rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +0 -57
- /rasa/cli/project_templates/{finance/tests/e2e_test_cases → basic/tests/e2e_test_cases/without_stub}/general/hello.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{accounts → without_stub/accounts}/check_balance.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{accounts → without_stub/accounts}/download_statements.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{cards → without_stub/cards}/block_card.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/bot_challenge.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/feedback.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/goodbye.yml +0 -0
- /rasa/cli/project_templates/{telco/tests/e2e_test_cases → finance/tests/e2e_test_cases/without_stub}/general/hello.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/human_handoff.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/patterns.yml +0 -0
- /rasa/cli/project_templates/finance/tests/e2e_test_cases/{transfers → without_stub/transfers}/transfer_money.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{billing → without_stub/billing}/understand_bill.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/bot_challenge.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/feedback.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/goodbye.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/human_handoff.yml +0 -0
- /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/patterns.yml +0 -0
- {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/entry_points.txt +0 -0
|
@@ -7,6 +7,7 @@ from typing import Literal, Optional
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
9
9
|
from rasa.cli.validation.config_path_validation import get_validated_path
|
|
10
|
+
from rasa.core.available_agents import DEFAULT_AGENTS_CONFIG_FOLDER, AvailableAgents
|
|
10
11
|
from rasa.core.config.available_endpoints import AvailableEndpoints
|
|
11
12
|
from rasa.core.config.credentials import CredentialsConfig
|
|
12
13
|
from rasa.core.config.message_procesing_config import MessageProcessingConfig
|
|
@@ -146,10 +147,12 @@ class Configuration:
|
|
|
146
147
|
def __init__(
|
|
147
148
|
self,
|
|
148
149
|
endpoints: AvailableEndpoints,
|
|
150
|
+
available_agents: AvailableAgents,
|
|
149
151
|
credentials: Optional[CredentialsConfig] = None,
|
|
150
152
|
message_processing_config: Optional[MessageProcessingConfig] = None,
|
|
151
153
|
):
|
|
152
154
|
self.credentials = credentials
|
|
155
|
+
self.available_agents = available_agents
|
|
153
156
|
self.endpoints = endpoints
|
|
154
157
|
self.message_processing_config = message_processing_config
|
|
155
158
|
|
|
@@ -159,6 +162,7 @@ class Configuration:
|
|
|
159
162
|
cls._instance = Configuration(
|
|
160
163
|
credentials=None,
|
|
161
164
|
endpoints=AvailableEndpoints(),
|
|
165
|
+
available_agents=AvailableAgents(),
|
|
162
166
|
message_processing_config=None,
|
|
163
167
|
)
|
|
164
168
|
return cls._instance
|
|
@@ -177,7 +181,10 @@ class Configuration:
|
|
|
177
181
|
)
|
|
178
182
|
if cls._instance is None:
|
|
179
183
|
cls._instance = Configuration(
|
|
180
|
-
endpoints=endpoints,
|
|
184
|
+
endpoints=endpoints,
|
|
185
|
+
available_agents=AvailableAgents(),
|
|
186
|
+
credentials=None,
|
|
187
|
+
message_processing_config=None,
|
|
181
188
|
)
|
|
182
189
|
else:
|
|
183
190
|
cls._instance.endpoints = endpoints
|
|
@@ -189,6 +196,7 @@ class Configuration:
|
|
|
189
196
|
if cls._instance is None:
|
|
190
197
|
cls._instance = Configuration(
|
|
191
198
|
endpoints=AvailableEndpoints(),
|
|
199
|
+
available_agents=AvailableAgents(),
|
|
192
200
|
credentials=None,
|
|
193
201
|
message_processing_config=None,
|
|
194
202
|
)
|
|
@@ -217,6 +225,7 @@ class Configuration:
|
|
|
217
225
|
message_processing_config=message_processing_config,
|
|
218
226
|
credentials=None,
|
|
219
227
|
endpoints=AvailableEndpoints(),
|
|
228
|
+
available_agents=AvailableAgents(),
|
|
220
229
|
)
|
|
221
230
|
else:
|
|
222
231
|
cls._instance.message_processing_config = message_processing_config
|
|
@@ -240,12 +249,37 @@ class Configuration:
|
|
|
240
249
|
cls._instance = Configuration(
|
|
241
250
|
credentials=credentials,
|
|
242
251
|
endpoints=AvailableEndpoints(),
|
|
252
|
+
available_agents=AvailableAgents(),
|
|
243
253
|
message_processing_config=None,
|
|
244
254
|
)
|
|
245
255
|
else:
|
|
246
256
|
cls._instance.credentials = credentials
|
|
247
257
|
return cls._instance
|
|
248
258
|
|
|
259
|
+
@classmethod
|
|
260
|
+
def initialise_sub_agents(cls, sub_agents_path: Optional[Path]) -> Configuration:
|
|
261
|
+
sub_agents_folder = (
|
|
262
|
+
str(sub_agents_path)
|
|
263
|
+
if sub_agents_path is not None
|
|
264
|
+
else DEFAULT_AGENTS_CONFIG_FOLDER
|
|
265
|
+
)
|
|
266
|
+
logger.debug(
|
|
267
|
+
"configuration.initialise_sub_agents.start",
|
|
268
|
+
sub_agents_folder=sub_agents_folder,
|
|
269
|
+
)
|
|
270
|
+
available_agents = AvailableAgents.read_from_folder(sub_agents_folder)
|
|
271
|
+
|
|
272
|
+
if cls._instance is None:
|
|
273
|
+
cls._instance = Configuration(
|
|
274
|
+
endpoints=AvailableEndpoints(),
|
|
275
|
+
available_agents=available_agents,
|
|
276
|
+
credentials=None,
|
|
277
|
+
message_processing_config=None,
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
cls._instance.available_agents = available_agents
|
|
281
|
+
return cls._instance
|
|
282
|
+
|
|
249
283
|
@classmethod
|
|
250
284
|
def get_instance(cls) -> Configuration:
|
|
251
285
|
if cls._instance is None:
|
|
@@ -254,6 +288,7 @@ class Configuration:
|
|
|
254
288
|
"Call appropriate 'initialise' methods to "
|
|
255
289
|
"load the config when Rasa Pro starts: "
|
|
256
290
|
"initialise_endpoints(), "
|
|
291
|
+
"initialise_sub_agents(), "
|
|
257
292
|
"initialise_credentials(), "
|
|
258
293
|
"initialise_message_processing()"
|
|
259
294
|
)
|
rasa/core/constants.py
CHANGED
|
@@ -123,3 +123,9 @@ SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME = (
|
|
|
123
123
|
"SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE"
|
|
124
124
|
)
|
|
125
125
|
AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME = "AWS_ELASTICACHE_CLUSTER_NAME"
|
|
126
|
+
RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME = "RDS_SQL_DB_AWS_IAM_ENABLED"
|
|
127
|
+
ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME = "ELASTICACHE_REDIS_AWS_IAM_ENABLED"
|
|
128
|
+
KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME = "KAFKA_MSK_AWS_IAM_ENABLED"
|
|
129
|
+
SQL_SERVICE_NAME = "sql"
|
|
130
|
+
REDIS_SERVICE_NAME = "redis"
|
|
131
|
+
KAFKA_SERVICE_NAME = "kafka"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import threading
|
|
3
3
|
import time
|
|
4
|
-
from typing import Optional, Tuple
|
|
4
|
+
from typing import Dict, Optional, Tuple
|
|
5
5
|
from urllib.parse import ParseResult, urlencode, urlunparse
|
|
6
6
|
|
|
7
7
|
import boto3
|
|
@@ -14,6 +14,14 @@ from botocore.session import get_session
|
|
|
14
14
|
from botocore.signers import RequestSigner
|
|
15
15
|
from cachetools import TTLCache, cached
|
|
16
16
|
|
|
17
|
+
from rasa.core.constants import (
|
|
18
|
+
ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
19
|
+
KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
20
|
+
KAFKA_SERVICE_NAME,
|
|
21
|
+
RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
22
|
+
REDIS_SERVICE_NAME,
|
|
23
|
+
SQL_SERVICE_NAME,
|
|
24
|
+
)
|
|
17
25
|
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
18
26
|
IAMCredentialsProvider,
|
|
19
27
|
IAMCredentialsProviderInput,
|
|
@@ -24,6 +32,25 @@ from rasa.shared.exceptions import ConnectionException
|
|
|
24
32
|
|
|
25
33
|
structlogger = structlog.get_logger(__name__)
|
|
26
34
|
|
|
35
|
+
SERVICE_CONFIG: Dict[Tuple[SupportedServiceType, str], str] = {
|
|
36
|
+
(
|
|
37
|
+
SupportedServiceType.TRACKER_STORE,
|
|
38
|
+
SQL_SERVICE_NAME,
|
|
39
|
+
): RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
40
|
+
(
|
|
41
|
+
SupportedServiceType.TRACKER_STORE,
|
|
42
|
+
REDIS_SERVICE_NAME,
|
|
43
|
+
): ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
44
|
+
(
|
|
45
|
+
SupportedServiceType.EVENT_BROKER,
|
|
46
|
+
KAFKA_SERVICE_NAME,
|
|
47
|
+
): KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
48
|
+
(
|
|
49
|
+
SupportedServiceType.LOCK_STORE,
|
|
50
|
+
REDIS_SERVICE_NAME,
|
|
51
|
+
): ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
|
|
52
|
+
}
|
|
53
|
+
|
|
27
54
|
|
|
28
55
|
class AWSRDSIAMCredentialsProvider(IAMCredentialsProvider):
|
|
29
56
|
"""Generates temporary credentials for AWS RDS using IAM roles."""
|
|
@@ -203,21 +230,59 @@ class AWSElasticacheRedisIAMCredentialsProvider(redis.CredentialProvider):
|
|
|
203
230
|
return TemporaryCredentials()
|
|
204
231
|
|
|
205
232
|
|
|
233
|
+
def is_iam_enabled(provider_input: "IAMCredentialsProviderInput") -> bool:
|
|
234
|
+
"""Checks if IAM authentication is enabled for the given service."""
|
|
235
|
+
service_type = provider_input.service_type
|
|
236
|
+
service_name = provider_input.service_name
|
|
237
|
+
iam_enabled_env_var_name = SERVICE_CONFIG.get((service_type, service_name))
|
|
238
|
+
|
|
239
|
+
if not iam_enabled_env_var_name:
|
|
240
|
+
structlogger.warning(
|
|
241
|
+
"rasa.core.aws_iam_credentials_providers.is_iam_enabled.unsupported_service",
|
|
242
|
+
event_info=f"IAM authentication check requested for unsupported service: "
|
|
243
|
+
f"{service_name}",
|
|
244
|
+
)
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
return os.getenv(iam_enabled_env_var_name, "false").lower() == "true"
|
|
248
|
+
|
|
249
|
+
|
|
206
250
|
def create_aws_iam_credentials_provider(
|
|
207
251
|
provider_input: "IAMCredentialsProviderInput",
|
|
208
252
|
) -> Optional["IAMCredentialsProvider"]:
|
|
209
253
|
"""Factory function to create an AWS IAM credentials provider."""
|
|
210
|
-
|
|
254
|
+
iam_enabled = is_iam_enabled(provider_input)
|
|
255
|
+
if not iam_enabled:
|
|
256
|
+
structlogger.debug(
|
|
257
|
+
"rasa.core.aws_iam_credentials_providers.create_provider.iam_not_enabled",
|
|
258
|
+
event_info=f"IAM authentication not enabled for service: "
|
|
259
|
+
f"{provider_input.service_type}",
|
|
260
|
+
)
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
if (
|
|
264
|
+
provider_input.service_type == SupportedServiceType.TRACKER_STORE
|
|
265
|
+
and provider_input.service_name == SQL_SERVICE_NAME
|
|
266
|
+
):
|
|
211
267
|
return AWSRDSIAMCredentialsProvider(
|
|
212
268
|
username=provider_input.username,
|
|
213
269
|
host=provider_input.host,
|
|
214
270
|
port=provider_input.port,
|
|
215
271
|
)
|
|
216
272
|
|
|
217
|
-
if
|
|
273
|
+
if (
|
|
274
|
+
provider_input.service_type == SupportedServiceType.TRACKER_STORE
|
|
275
|
+
and provider_input.service_name == REDIS_SERVICE_NAME
|
|
276
|
+
):
|
|
277
|
+
return AWSElasticacheRedisIAMCredentialsProvider(
|
|
278
|
+
username=provider_input.username,
|
|
279
|
+
cluster_name=provider_input.cluster_name,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
if provider_input.service_type == SupportedServiceType.EVENT_BROKER:
|
|
218
283
|
return AWSMSKafkaIAMCredentialsProvider()
|
|
219
284
|
|
|
220
|
-
if provider_input.
|
|
285
|
+
if provider_input.service_type == SupportedServiceType.LOCK_STORE:
|
|
221
286
|
return AWSElasticacheRedisIAMCredentialsProvider(
|
|
222
287
|
username=provider_input.username,
|
|
223
288
|
cluster_name=provider_input.cluster_name,
|
|
@@ -47,7 +47,8 @@ class SupportedServiceType(Enum):
|
|
|
47
47
|
class IAMCredentialsProviderInput(BaseModel):
|
|
48
48
|
"""Input data for creating an IAM credentials provider."""
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
service_type: SupportedServiceType
|
|
51
|
+
service_name: str
|
|
51
52
|
username: Optional[str] = None
|
|
52
53
|
host: Optional[str] = None
|
|
53
54
|
port: Optional[int] = None
|
rasa/core/lock_store.py
CHANGED
|
@@ -18,6 +18,9 @@ from pydantic import (
|
|
|
18
18
|
|
|
19
19
|
import rasa.shared.utils.common
|
|
20
20
|
from rasa.core.constants import DEFAULT_LOCK_LIFETIME, IAM_CLOUD_PROVIDER_ENV_VAR_NAME
|
|
21
|
+
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
22
|
+
SupportedServiceType,
|
|
23
|
+
)
|
|
21
24
|
from rasa.core.lock import TicketLock
|
|
22
25
|
from rasa.core.redis_connection_factory import (
|
|
23
26
|
DeploymentMode,
|
|
@@ -336,6 +339,7 @@ class RedisLockStore(LockStore):
|
|
|
336
339
|
redis_config = RedisConfig(
|
|
337
340
|
host=str(self.config.host),
|
|
338
341
|
port=self.config.port,
|
|
342
|
+
service_type=SupportedServiceType.LOCK_STORE,
|
|
339
343
|
db=self.config.db,
|
|
340
344
|
username=self.config.username,
|
|
341
345
|
password=self.config.password,
|
|
@@ -16,7 +16,7 @@ from rasa.agents.constants import (
|
|
|
16
16
|
from rasa.agents.core.types import AgentStatus, ProtocolType
|
|
17
17
|
from rasa.agents.schemas import AgentInput, AgentOutput
|
|
18
18
|
from rasa.agents.schemas.agent_input import AgentInputSlot
|
|
19
|
-
from rasa.core.
|
|
19
|
+
from rasa.core.config.configuration import Configuration
|
|
20
20
|
from rasa.core.policies.flows.flow_step_result import (
|
|
21
21
|
ContinueFlowWithNextStep,
|
|
22
22
|
FlowActionPrediction,
|
|
@@ -47,12 +47,13 @@ from rasa.shared.core.events import (
|
|
|
47
47
|
AgentStarted,
|
|
48
48
|
Event,
|
|
49
49
|
SlotSet,
|
|
50
|
+
deserialise_events,
|
|
50
51
|
)
|
|
51
52
|
from rasa.shared.core.flows.steps import (
|
|
52
53
|
CallFlowStep,
|
|
53
54
|
)
|
|
54
55
|
from rasa.shared.core.slots import CategoricalSlot, Slot
|
|
55
|
-
from rasa.shared.core.trackers import DialogueStateTracker
|
|
56
|
+
from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
|
|
56
57
|
from rasa.shared.utils.llm import tracker_as_readable_transcript
|
|
57
58
|
|
|
58
59
|
structlogger = structlog.get_logger()
|
|
@@ -61,8 +62,9 @@ MAX_AGENT_RETRIES = 3
|
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
def remove_agent_stack_frame(stack: DialogueStack, agent_id: str) -> None:
|
|
64
|
-
"""Finishes the agentic loop by popping the agent stack frame from
|
|
65
|
-
|
|
65
|
+
"""Finishes the agentic loop by popping the agent stack frame from provided `stack`.
|
|
66
|
+
|
|
67
|
+
The `tracker.stack` is NOT modified.
|
|
66
68
|
"""
|
|
67
69
|
agent_stack_frame = stack.find_agent_stack_frame_by_agent(agent_id)
|
|
68
70
|
if not agent_stack_frame:
|
|
@@ -136,7 +138,9 @@ async def run_agent(
|
|
|
136
138
|
final_events.append(AgentStarted(step.call, step.flow_id))
|
|
137
139
|
|
|
138
140
|
# send the input to the agent and wait for a response
|
|
139
|
-
protocol_type = get_protocol_type(
|
|
141
|
+
protocol_type = get_protocol_type(
|
|
142
|
+
step, Configuration.get_instance().available_agents.get_agent_config(step.call)
|
|
143
|
+
)
|
|
140
144
|
output: AgentOutput = await _call_agent_with_retry(
|
|
141
145
|
agent_name=step.call,
|
|
142
146
|
protocol_type=protocol_type,
|
|
@@ -471,8 +475,9 @@ def _create_action_prediction(
|
|
|
471
475
|
def _create_agent_request_user_input_prediction(
|
|
472
476
|
message: Optional[str], events: Optional[List[Event]]
|
|
473
477
|
) -> FlowActionPrediction:
|
|
474
|
-
"""Create a prediction for requesting user input from the agent
|
|
475
|
-
|
|
478
|
+
"""Create a prediction for requesting user input from the agent and waiting for it.
|
|
479
|
+
|
|
480
|
+
This function creates a prediction that will pause the flow and wait for user input.
|
|
476
481
|
"""
|
|
477
482
|
return _create_action_prediction(
|
|
478
483
|
ACTION_AGENT_REQUEST_USER_INPUT_NAME, message, events
|
|
@@ -529,7 +534,9 @@ def _prepare_agent_input(
|
|
|
529
534
|
tracker.current_slot_values(), slots, step.exit_if
|
|
530
535
|
),
|
|
531
536
|
conversation_history=tracker_as_readable_transcript(tracker),
|
|
532
|
-
events=
|
|
537
|
+
events=deserialise_events(
|
|
538
|
+
tracker.current_state(EventVerbosity.ALL).get("events") or []
|
|
539
|
+
),
|
|
533
540
|
metadata=agent_input_metadata,
|
|
534
541
|
)
|
|
535
542
|
|
|
@@ -550,6 +557,7 @@ def _prepare_slots_for_agent(
|
|
|
550
557
|
Args:
|
|
551
558
|
slot_values: The full slot dictionary from the tracker.
|
|
552
559
|
slot_definitions: The slot definitions from the domain.
|
|
560
|
+
exit_if: Optional list of exit conditions that determine which slots to keep.
|
|
553
561
|
|
|
554
562
|
Returns:
|
|
555
563
|
A list of slots containing the name, current value, type, and allowed values.
|
|
@@ -6,7 +6,10 @@ import redis
|
|
|
6
6
|
import structlog
|
|
7
7
|
from pydantic import BaseModel, ConfigDict
|
|
8
8
|
|
|
9
|
-
from rasa.core.constants import
|
|
9
|
+
from rasa.core.constants import (
|
|
10
|
+
AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME,
|
|
11
|
+
REDIS_SERVICE_NAME,
|
|
12
|
+
)
|
|
10
13
|
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
11
14
|
IAMCredentialsProvider,
|
|
12
15
|
IAMCredentialsProviderInput,
|
|
@@ -65,6 +68,7 @@ class RedisConfig(BaseModel):
|
|
|
65
68
|
|
|
66
69
|
host: Text = "localhost"
|
|
67
70
|
port: int = 6379
|
|
71
|
+
service_type: SupportedServiceType
|
|
68
72
|
username: Optional[Text] = None
|
|
69
73
|
password: Optional[Text] = None
|
|
70
74
|
use_ssl: bool = False
|
|
@@ -117,7 +121,8 @@ class RedisConnectionFactory:
|
|
|
117
121
|
|
|
118
122
|
iam_credentials_provider = create_iam_credentials_provider(
|
|
119
123
|
IAMCredentialsProviderInput(
|
|
120
|
-
|
|
124
|
+
service_type=config.service_type,
|
|
125
|
+
service_name=REDIS_SERVICE_NAME,
|
|
121
126
|
username=config.username,
|
|
122
127
|
cluster_name=os.getenv(AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME),
|
|
123
128
|
)
|
|
@@ -8,6 +8,9 @@ from pydantic import ValidationError
|
|
|
8
8
|
|
|
9
9
|
import rasa.shared
|
|
10
10
|
from rasa.core.brokers.broker import EventBroker
|
|
11
|
+
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
12
|
+
SupportedServiceType,
|
|
13
|
+
)
|
|
11
14
|
from rasa.core.redis_connection_factory import (
|
|
12
15
|
DeploymentMode,
|
|
13
16
|
RedisConfig,
|
|
@@ -54,6 +57,7 @@ class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
|
54
57
|
config = RedisConfig(
|
|
55
58
|
host=host,
|
|
56
59
|
port=port,
|
|
60
|
+
service_type=SupportedServiceType.TRACKER_STORE,
|
|
57
61
|
db=db,
|
|
58
62
|
username=username,
|
|
59
63
|
password=password,
|
|
@@ -27,6 +27,7 @@ from rasa.core.constants import (
|
|
|
27
27
|
POSTGRESQL_MAX_OVERFLOW,
|
|
28
28
|
POSTGRESQL_POOL_SIZE,
|
|
29
29
|
POSTGRESQL_SCHEMA,
|
|
30
|
+
SQL_SERVICE_NAME,
|
|
30
31
|
SQL_TRACKER_STORE_SSL_MODE_ENV_VAR_NAME,
|
|
31
32
|
SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME,
|
|
32
33
|
)
|
|
@@ -229,7 +230,8 @@ class SQLTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
|
229
230
|
|
|
230
231
|
iam_credentials_provider = create_iam_credentials_provider(
|
|
231
232
|
IAMCredentialsProviderInput(
|
|
232
|
-
|
|
233
|
+
service_type=SupportedServiceType.TRACKER_STORE,
|
|
234
|
+
service_name=SQL_SERVICE_NAME,
|
|
233
235
|
username=username,
|
|
234
236
|
host=host,
|
|
235
237
|
port=port,
|
|
@@ -104,7 +104,10 @@ class StartFlowCommand(Command):
|
|
|
104
104
|
# predicted a start flow command for the flow which is on top of the stack,
|
|
105
105
|
# we just need to remove the pattern_continue_interrupted frame(s) from the
|
|
106
106
|
# stack
|
|
107
|
-
stack = remove_pattern_continue_interrupted_frames(
|
|
107
|
+
stack, flow_completed_events = remove_pattern_continue_interrupted_frames(
|
|
108
|
+
stack
|
|
109
|
+
)
|
|
110
|
+
applied_events.extend(flow_completed_events)
|
|
108
111
|
return applied_events + tracker.create_stack_updated_events(stack)
|
|
109
112
|
|
|
110
113
|
# if the flow is already on the stack, resume it
|
|
@@ -114,7 +117,10 @@ class StartFlowCommand(Command):
|
|
|
114
117
|
):
|
|
115
118
|
# if pattern_continue_interrupted is active, we need to remove it
|
|
116
119
|
# from the stack before resuming the flow
|
|
117
|
-
stack = remove_pattern_continue_interrupted_frames(
|
|
120
|
+
stack, flow_completed_events = remove_pattern_continue_interrupted_frames(
|
|
121
|
+
stack
|
|
122
|
+
)
|
|
123
|
+
applied_events.extend(flow_completed_events)
|
|
118
124
|
applied_events.extend(resume_flow(self.flow, tracker, stack))
|
|
119
125
|
# the current active flow is interrupted
|
|
120
126
|
applied_events.append(
|
|
@@ -128,7 +134,8 @@ class StartFlowCommand(Command):
|
|
|
128
134
|
|
|
129
135
|
# remove the pattern_continue_interrupted frames from the stack
|
|
130
136
|
# if it is currently active but the user digressed from the pattern
|
|
131
|
-
stack = remove_pattern_continue_interrupted_frames(stack)
|
|
137
|
+
stack, flow_completed_events = remove_pattern_continue_interrupted_frames(stack)
|
|
138
|
+
applied_events.extend(flow_completed_events)
|
|
132
139
|
|
|
133
140
|
if original_top_flow:
|
|
134
141
|
# if the original top flow is not the same as the flow to start,
|
|
@@ -19,6 +19,7 @@ from rasa.shared.constants import ACTION_ASK_PREFIX, UTTER_ASK_PREFIX
|
|
|
19
19
|
from rasa.shared.core.events import (
|
|
20
20
|
AgentResumed,
|
|
21
21
|
Event,
|
|
22
|
+
FlowCompleted,
|
|
22
23
|
FlowResumed,
|
|
23
24
|
SlotSet,
|
|
24
25
|
)
|
|
@@ -250,18 +251,28 @@ def collect_frames_to_resume(
|
|
|
250
251
|
return list(frames_to_resume), frame_to_resume
|
|
251
252
|
|
|
252
253
|
|
|
253
|
-
def remove_pattern_continue_interrupted_frames(
|
|
254
|
-
|
|
254
|
+
def remove_pattern_continue_interrupted_frames(
|
|
255
|
+
stack: DialogueStack,
|
|
256
|
+
) -> Tuple[DialogueStack, List[FlowCompleted]]:
|
|
257
|
+
"""Remove pattern_continue_interrupted frames from the stack and return events.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
A tuple containing (updated_stack, flow_completed_events)
|
|
261
|
+
"""
|
|
255
262
|
from rasa.dialogue_understanding.stack.utils import (
|
|
256
263
|
is_continue_interrupted_flow_active,
|
|
257
264
|
)
|
|
258
265
|
|
|
259
266
|
if not is_continue_interrupted_flow_active(stack):
|
|
260
|
-
return stack
|
|
267
|
+
return stack, []
|
|
261
268
|
|
|
269
|
+
events = []
|
|
262
270
|
# remove pattern_continue_interrupted from the stack
|
|
263
271
|
top_frame = stack.top()
|
|
264
272
|
while isinstance(top_frame, PatternFlowStackFrame):
|
|
273
|
+
# Create FlowCompleted event for the pattern frame being removed
|
|
274
|
+
events.append(FlowCompleted(top_frame.flow_id, top_frame.step_id))
|
|
275
|
+
|
|
265
276
|
# If the top frame is a pattern frame, we need to remove it
|
|
266
277
|
# before continuing with the active user flow frame.
|
|
267
278
|
# This prevents the pattern frame
|
|
@@ -271,4 +282,4 @@ def remove_pattern_continue_interrupted_frames(stack: DialogueStack) -> Dialogue
|
|
|
271
282
|
stack.pop()
|
|
272
283
|
top_frame = stack.top()
|
|
273
284
|
|
|
274
|
-
return stack
|
|
285
|
+
return stack, events
|
|
@@ -7,7 +7,7 @@ from jinja2 import Environment, Template, select_autoescape
|
|
|
7
7
|
|
|
8
8
|
import rasa.dialogue_understanding.generator.utils
|
|
9
9
|
import rasa.shared.utils.io
|
|
10
|
-
from rasa.core.
|
|
10
|
+
from rasa.core.config.configuration import Configuration
|
|
11
11
|
from rasa.dialogue_understanding.commands import (
|
|
12
12
|
Command,
|
|
13
13
|
SetSlotCommand,
|
|
@@ -398,7 +398,9 @@ class LLMBasedCommandGenerator(
|
|
|
398
398
|
if isinstance(event, AgentStarted) and event.flow_id == flow.id
|
|
399
399
|
]
|
|
400
400
|
available_agents = [
|
|
401
|
-
|
|
401
|
+
Configuration.get_instance().available_agents.get_agent_config(
|
|
402
|
+
event.agent_id
|
|
403
|
+
)
|
|
402
404
|
for event in agent_events
|
|
403
405
|
]
|
|
404
406
|
if available_agents:
|
|
@@ -2,7 +2,7 @@ from typing import Any, Dict, Literal, Optional, Text
|
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
from rasa.core.
|
|
5
|
+
from rasa.core.config.configuration import Configuration
|
|
6
6
|
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
7
7
|
CommandSyntaxVersion,
|
|
8
8
|
)
|
|
@@ -125,7 +125,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
125
125
|
"""Get the default prompt template file name for the command generator."""
|
|
126
126
|
return (
|
|
127
127
|
AGENT_DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
128
|
-
if
|
|
128
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
129
129
|
else DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
130
130
|
)
|
|
131
131
|
|
|
@@ -134,7 +134,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
134
134
|
"""Get the fallback prompt template file name for the command generator."""
|
|
135
135
|
return (
|
|
136
136
|
AGENT_FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
137
|
-
if
|
|
137
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
138
138
|
else FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
139
139
|
)
|
|
140
140
|
|
|
@@ -143,7 +143,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
143
143
|
"""Get the model prompt mapper for the command generator."""
|
|
144
144
|
return (
|
|
145
145
|
AGENT_MODEL_PROMPT_MAPPER
|
|
146
|
-
if
|
|
146
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
147
147
|
else MODEL_PROMPT_MAPPER
|
|
148
148
|
)
|
|
149
149
|
|
|
@@ -2,7 +2,7 @@ from typing import Any, Dict, Literal, Optional, Text
|
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
from rasa.core.
|
|
5
|
+
from rasa.core.config.configuration import Configuration
|
|
6
6
|
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
7
7
|
CommandSyntaxVersion,
|
|
8
8
|
)
|
|
@@ -127,7 +127,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
127
127
|
"""Get the default prompt template file name for the command generator."""
|
|
128
128
|
return (
|
|
129
129
|
AGENT_DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
130
|
-
if
|
|
130
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
131
131
|
else DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
132
132
|
)
|
|
133
133
|
|
|
@@ -136,7 +136,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
136
136
|
"""Get the fallback prompt template file name for the command generator."""
|
|
137
137
|
return (
|
|
138
138
|
AGENT_FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
139
|
-
if
|
|
139
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
140
140
|
else FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
|
|
141
141
|
)
|
|
142
142
|
|
|
@@ -145,7 +145,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
|
|
|
145
145
|
"""Get the model prompt mapper for the command generator."""
|
|
146
146
|
return (
|
|
147
147
|
AGENT_MODEL_PROMPT_MAPPER
|
|
148
|
-
if
|
|
148
|
+
if Configuration.get_instance().available_agents.has_agents()
|
|
149
149
|
else MODEL_PROMPT_MAPPER
|
|
150
150
|
)
|
|
151
151
|
|
rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py
CHANGED
|
@@ -9,7 +9,7 @@ from rasa.agents.utils import (
|
|
|
9
9
|
get_active_agent_info,
|
|
10
10
|
get_completed_agents_info,
|
|
11
11
|
)
|
|
12
|
-
from rasa.core.
|
|
12
|
+
from rasa.core.config.configuration import Configuration
|
|
13
13
|
from rasa.dialogue_understanding.commands import (
|
|
14
14
|
CannotHandleCommand,
|
|
15
15
|
Command,
|
|
@@ -403,7 +403,7 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
|
|
|
403
403
|
current_slot_allowed_values = allowed_values_for_slot(
|
|
404
404
|
tracker.slots.get(current_slot)
|
|
405
405
|
)
|
|
406
|
-
has_agents =
|
|
406
|
+
has_agents = Configuration.get_instance().available_agents.has_agents()
|
|
407
407
|
current_conversation = tracker_as_readable_transcript(
|
|
408
408
|
tracker, highlight_agent_turns=has_agents
|
|
409
409
|
)
|
|
@@ -6,9 +6,9 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
6
6
|
import structlog
|
|
7
7
|
from tqdm import tqdm
|
|
8
8
|
|
|
9
|
-
from rasa.core.available_agents import AvailableAgents
|
|
10
9
|
from rasa.core.channels import CollectingOutputChannel, UserMessage
|
|
11
10
|
from rasa.core.config.available_endpoints import AvailableEndpoints
|
|
11
|
+
from rasa.core.config.configuration import Configuration
|
|
12
12
|
from rasa.core.exceptions import AgentNotReady
|
|
13
13
|
from rasa.core.persistor import StorageType
|
|
14
14
|
from rasa.dialogue_understanding.commands import Command
|
|
@@ -71,7 +71,7 @@ class DialogueUnderstandingTestRunner:
|
|
|
71
71
|
import rasa.core.agent
|
|
72
72
|
|
|
73
73
|
self._check_action_server(endpoints)
|
|
74
|
-
sub_agents =
|
|
74
|
+
sub_agents = Configuration.get_instance().available_agents
|
|
75
75
|
|
|
76
76
|
self.agent = asyncio.run(
|
|
77
77
|
rasa.core.agent.load_agent(
|
rasa/e2e_test/e2e_test_runner.py
CHANGED
|
@@ -13,9 +13,9 @@ import structlog
|
|
|
13
13
|
from tqdm import tqdm
|
|
14
14
|
|
|
15
15
|
import rasa.shared.utils.io
|
|
16
|
-
from rasa.core.available_agents import AvailableAgents
|
|
17
16
|
from rasa.core.channels import CollectingOutputChannel, UserMessage
|
|
18
17
|
from rasa.core.config.available_endpoints import AvailableEndpoints
|
|
18
|
+
from rasa.core.config.configuration import Configuration
|
|
19
19
|
from rasa.core.constants import ACTIVE_FLOW_METADATA_KEY, STEP_ID_METADATA_KEY
|
|
20
20
|
from rasa.core.exceptions import AgentNotReady
|
|
21
21
|
from rasa.core.persistor import StorageType
|
|
@@ -96,7 +96,7 @@ class E2ETestRunner:
|
|
|
96
96
|
if endpoints and not are_custom_actions_stubbed:
|
|
97
97
|
self._action_server_is_reachable(endpoints)
|
|
98
98
|
|
|
99
|
-
sub_agents =
|
|
99
|
+
sub_agents = Configuration.get_instance().available_agents
|
|
100
100
|
|
|
101
101
|
self.agent = asyncio.run(
|
|
102
102
|
rasa.core.agent.load_agent(
|