rasa-pro 3.12.4__py3-none-any.whl → 3.12.6.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (29) hide show
  1. rasa/core/channels/voice_ready/audiocodes.py +6 -0
  2. rasa/core/channels/voice_stream/audiocodes.py +53 -9
  3. rasa/core/channels/voice_stream/genesys.py +146 -16
  4. rasa/core/policies/intentless_policy.py +6 -59
  5. rasa/dialogue_understanding/generator/_jinja_filters.py +9 -0
  6. rasa/dialogue_understanding/generator/constants.py +4 -0
  7. rasa/dialogue_understanding/generator/llm_based_command_generator.py +20 -4
  8. rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -1
  9. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +2 -2
  10. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +2 -2
  11. rasa/dialogue_understanding/processor/command_processor.py +20 -5
  12. rasa/dialogue_understanding/processor/command_processor_component.py +5 -2
  13. rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +1 -1
  14. rasa/engine/validation.py +36 -1
  15. rasa/model_training.py +2 -1
  16. rasa/shared/constants.py +2 -0
  17. rasa/shared/core/domain.py +12 -3
  18. rasa/shared/core/policies/__init__.py +0 -0
  19. rasa/shared/core/policies/utils.py +87 -0
  20. rasa/shared/core/slot_mappings.py +12 -0
  21. rasa/tracing/instrumentation/attribute_extractors.py +2 -0
  22. rasa/version.py +2 -1
  23. {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dev1.dist-info}/METADATA +4 -7
  24. {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dev1.dist-info}/RECORD +27 -26
  25. {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dev1.dist-info}/WHEEL +1 -1
  26. README.md +0 -38
  27. rasa/keys +0 -1
  28. {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dev1.dist-info}/NOTICE +0 -0
  29. {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dev1.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import copy
3
+ import hmac
3
4
  import json
4
5
  import uuid
5
6
  from collections import defaultdict
@@ -245,8 +246,13 @@ class AudiocodesInput(InputChannel):
245
246
 
246
247
  def _check_token(self, token: Optional[Text]) -> None:
247
248
  if not token:
249
+ structlogger.error("audiocodes.token_not_provided")
248
250
  raise HttpUnauthorized("Authentication token required.")
249
251
 
252
+ if not hmac.compare_digest(str(token), str(self.token)):
253
+ structlogger.error("audiocodes.invalid_token", invalid_token=token)
254
+ raise HttpUnauthorized("Invalid authentication token.")
255
+
250
256
  def _get_conversation(
251
257
  self, token: Optional[Text], conversation_id: Text
252
258
  ) -> Conversation:
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import base64
3
+ import hmac
3
4
  import json
4
5
  from typing import Any, Awaitable, Callable, Dict, Optional, Text
5
6
 
@@ -103,6 +104,7 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
103
104
 
104
105
  def __init__(
105
106
  self,
107
+ token: Optional[Text],
106
108
  server_url: str,
107
109
  asr_config: Dict,
108
110
  tts_config: Dict,
@@ -110,6 +112,22 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
110
112
  ):
111
113
  mark_as_beta_feature("Audiocodes (audiocodes_stream) Channel")
112
114
  super().__init__(server_url, asr_config, tts_config, monitor_silence)
115
+ self.token = token
116
+
117
+ @classmethod
118
+ def from_credentials(
119
+ cls, credentials: Optional[Dict[str, Any]]
120
+ ) -> VoiceInputChannel:
121
+ if not credentials:
122
+ raise ValueError("No credentials given for Audiocodes voice channel.")
123
+
124
+ return cls(
125
+ token=credentials.get("token"),
126
+ server_url=credentials["server_url"],
127
+ asr_config=credentials["asr"],
128
+ tts_config=credentials["tts"],
129
+ monitor_silence=credentials.get("monitor_silence", False),
130
+ )
113
131
 
114
132
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
115
133
  return RasaAudioBytes(base64.b64decode(input_bytes))
@@ -135,6 +153,13 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
135
153
  )
136
154
  if activity["name"] == "start":
137
155
  return map_call_params(activity["parameters"])
156
+ elif data["type"] == "connection.validate":
157
+ # not part of call flow; only sent when integration is created
158
+ logger.info(
159
+ "audiocodes_stream.collect_call_parameters.connection.validate",
160
+ event_info="received request to validate integration",
161
+ )
162
+ self._send_validated(channel_websocket, data)
138
163
  else:
139
164
  logger.warning("audiocodes_stream.unknown_message", data=data)
140
165
  return None
@@ -158,7 +183,7 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
158
183
  elif activity["name"] == "playFinished":
159
184
  logger.debug("audiocodes_stream.playFinished", data=activity)
160
185
  if call_state.should_hangup:
161
- logger.info("audiocodes.hangup")
186
+ logger.info("audiocodes_stream.hangup")
162
187
  self._send_hangup(ws, data)
163
188
  # the conversation should continue until
164
189
  # we receive a end message from audiocodes
@@ -180,11 +205,10 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
180
205
  elif data["type"] == "session.end":
181
206
  logger.debug("audiocodes_stream.end", data=data)
182
207
  return EndConversationAction()
183
- elif data["type"] == "connection.validate":
184
- # not part of call flow; only sent when integration is created
185
- self._send_validated(ws, data)
186
208
  else:
187
- logger.warning("audiocodes_stream.unknown_message", data=data)
209
+ logger.warning(
210
+ "audiocodes_stream.map_input_message.unknown_message", data=data
211
+ )
188
212
 
189
213
  return ContinueConversationAction()
190
214
 
@@ -254,6 +278,17 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
254
278
  self.tts_cache,
255
279
  )
256
280
 
281
+ def _is_token_valid(self, token: Optional[Text]) -> bool:
282
+ # If no token is set, always return True
283
+ if not self.token:
284
+ return True
285
+
286
+ # Token is required, but not provided
287
+ if not token:
288
+ return False
289
+
290
+ return hmac.compare_digest(str(self.token), str(token))
291
+
257
292
  def blueprint(
258
293
  self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
259
294
  ) -> Blueprint:
@@ -266,17 +301,26 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
266
301
 
267
302
  @blueprint.websocket("/websocket") # type: ignore
268
303
  async def receive(request: Request, ws: Websocket) -> None:
269
- # TODO: validate API key header
270
- logger.info("audiocodes.receive", message="Starting audio streaming")
304
+ if not self._is_token_valid(request.token):
305
+ logger.error(
306
+ "audiocodes_stream.invalid_token",
307
+ invalid_token=request.token,
308
+ )
309
+ await ws.close(code=1008, reason="Invalid token")
310
+ return
311
+
312
+ logger.info(
313
+ "audiocodes_stream.receive", event_info="Started websocket connection"
314
+ )
271
315
  try:
272
316
  await self.run_audio_streaming(on_new_message, ws)
273
317
  except Exception as e:
274
318
  logger.exception(
275
- "audiocodes.receive",
319
+ "audiocodes_stream.receive",
276
320
  message="Error during audio streaming",
277
321
  error=e,
278
322
  )
279
- # return 500 error
323
+ await ws.close(code=1011, reason="Error during audio streaming")
280
324
  raise
281
325
 
282
326
  return blueprint
@@ -1,4 +1,7 @@
1
1
  import asyncio
2
+ import base64
3
+ import hashlib
4
+ import hmac
2
5
  import json
3
6
  from typing import Any, Awaitable, Callable, Dict, Optional, Text
4
7
 
@@ -45,6 +48,7 @@ in the documentation but observed in their example app
45
48
  https://github.com/GenesysCloudBlueprints/audioconnector-server-reference-implementation
46
49
  """
47
50
  MAXIMUM_BINARY_MESSAGE_SIZE = 64000 # 64KB
51
+ HEADER_API_KEY = "X-Api-Key"
48
52
  logger = structlog.get_logger(__name__)
49
53
 
50
54
 
@@ -86,8 +90,31 @@ class GenesysInputChannel(VoiceInputChannel):
86
90
  def name(cls) -> str:
87
91
  return "genesys"
88
92
 
89
- def __init__(self, *args: Any, **kwargs: Any) -> None:
93
+ def __init__(
94
+ self, api_key: Text, client_secret: Optional[Text], *args: Any, **kwargs: Any
95
+ ) -> None:
90
96
  super().__init__(*args, **kwargs)
97
+ self.api_key = api_key
98
+ self.client_secret = client_secret
99
+
100
+ @classmethod
101
+ def from_credentials(
102
+ cls, credentials: Optional[Dict[str, Any]]
103
+ ) -> VoiceInputChannel:
104
+ if not credentials:
105
+ raise ValueError("No credentials given for Genesys voice channel.")
106
+
107
+ if not credentials.get("api_key"):
108
+ raise ValueError("No API key given for Genesys voice channel (api_key).")
109
+
110
+ return cls(
111
+ api_key=credentials["api_key"],
112
+ client_secret=credentials.get("client_secret"),
113
+ server_url=credentials["server_url"],
114
+ asr_config=credentials["asr"],
115
+ tts_config=credentials["tts"],
116
+ monitor_silence=credentials.get("monitor_silence", False),
117
+ )
91
118
 
92
119
  def _ensure_channel_data_initialized(self) -> None:
93
120
  """Initialize Genesys-specific channel data if not already present.
@@ -273,6 +300,93 @@ class GenesysInputChannel(VoiceInputChannel):
273
300
  logger.debug("genesys.disconnect", message=message)
274
301
  _schedule_ws_task(ws.send(json.dumps(message)))
275
302
 
303
+ def _calculate_signature(self, request: Request) -> str:
304
+ """Calculate the signature using request data."""
305
+ org_id = request.headers.get("Audiohook-Organization-Id")
306
+ session_id = request.headers.get("Audiohook-Session-Id")
307
+ correlation_id = request.headers.get("Audiohook-Correlation-Id")
308
+ api_key = request.headers.get(HEADER_API_KEY)
309
+
310
+ # order of components is important!
311
+ components = [
312
+ ("@request-target", "/webhooks/genesys/websocket"),
313
+ ("audiohook-session-id", session_id),
314
+ ("audiohook-organization-id", org_id),
315
+ ("audiohook-correlation-id", correlation_id),
316
+ (HEADER_API_KEY.lower(), api_key),
317
+ ("@authority", self.server_url),
318
+ ]
319
+
320
+ # Create signature base string
321
+ signing_string = ""
322
+ for name, value in components:
323
+ signing_string += f'"{name}": {value}\n'
324
+
325
+ # Add @signature-params
326
+ signature_input = request.headers["Signature-Input"]
327
+ _, params_str = signature_input.split("=", 1)
328
+ signing_string += f'"@signature-params": {params_str}'
329
+
330
+ # Calculate the HMAC signature
331
+ key_bytes = base64.b64decode(self.client_secret)
332
+ signature = hmac.new(
333
+ key_bytes, signing_string.encode("utf-8"), hashlib.sha256
334
+ ).digest()
335
+ return base64.b64encode(signature).decode("utf-8")
336
+
337
+ async def _verify_signature(self, request: Request) -> bool:
338
+ """Verify the HTTP message signature from Genesys."""
339
+ if not self.client_secret:
340
+ logger.info(
341
+ "genesys.verify_signature.no_client_secret",
342
+ event_info="Signature verification skipped",
343
+ )
344
+ return True # Skip verification if no client secret
345
+
346
+ signature = request.headers.get("Signature")
347
+ signature_input = request.headers.get("Signature-Input")
348
+ if not signature or not signature_input:
349
+ logger.error("genesys.signature.missing_signature_header")
350
+ return False
351
+
352
+ try:
353
+ actual_signature = signature.split("=", 1)[1].strip(':"')
354
+ expected_signature = self._calculate_signature(request)
355
+ return hmac.compare_digest(
356
+ expected_signature.encode("utf-8"), actual_signature.encode("utf-8")
357
+ )
358
+ except Exception as e:
359
+ logger.exception("genesys.signature.verification_error", error=e)
360
+ return False
361
+
362
+ def _ensure_required_headers(self, request: Request) -> bool:
363
+ """Ensure required headers are present in the request."""
364
+ required_headers = [
365
+ "Audiohook-Organization-Id",
366
+ "Audiohook-Correlation-Id",
367
+ "Audiohook-Session-Id",
368
+ HEADER_API_KEY,
369
+ ]
370
+
371
+ missing_headers = [
372
+ header for header in required_headers if header not in request.headers
373
+ ]
374
+
375
+ if missing_headers:
376
+ logger.error(
377
+ "genesys.missing_required_headers",
378
+ missing_headers=missing_headers,
379
+ )
380
+ return False
381
+ return True
382
+
383
+ def _ensure_api_key(self, request: Request) -> bool:
384
+ """Ensure the API key is present in the request."""
385
+ api_key = request.headers.get(HEADER_API_KEY)
386
+ if not hmac.compare_digest(str(self.api_key), str(api_key)):
387
+ return False
388
+ return True
389
+
276
390
  def blueprint(
277
391
  self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
278
392
  ) -> Blueprint:
@@ -289,23 +403,39 @@ class GenesysInputChannel(VoiceInputChannel):
289
403
  "genesys.receive",
290
404
  audiohook_session_id=request.headers.get("audiohook-session-id"),
291
405
  )
292
- # validate required headers
293
- required_headers = [
294
- "audiohook-organization-id",
295
- "audiohook-correlation-id",
296
- "audiohook-session-id",
297
- "x-api-key",
298
- ]
299
-
300
- for header in required_headers:
301
- if header not in request.headers:
302
- await ws.close(1008, f"Missing required header: {header}")
303
- return
304
-
305
- # TODO: validate API key header
406
+
407
+ # verify signature
408
+ if not await self._verify_signature(request):
409
+ logger.error("genesys.receive.invalid_signature")
410
+ await ws.close(code=1008, reason="Invalid signature")
411
+ return
412
+
413
+ # ensure required headers are present
414
+ if not self._ensure_required_headers(request):
415
+ await ws.close(code=1002, reason="Missing required headers")
416
+ return
417
+
418
+ # ensure API key is correct
419
+ if not self._ensure_api_key(request):
420
+ logger.error(
421
+ "genesys.receive.invalid_api_key",
422
+ invalid_api_key=request.headers.get(HEADER_API_KEY),
423
+ )
424
+ await ws.close(code=1008, reason="Invalid API key")
425
+ return
426
+
306
427
  # process audio streaming
307
428
  logger.info("genesys.receive", message="Starting audio streaming")
308
- await self.run_audio_streaming(on_new_message, ws)
429
+ try:
430
+ await self.run_audio_streaming(on_new_message, ws)
431
+ except Exception as e:
432
+ logger.exception(
433
+ "genesys.receive",
434
+ message="Error during audio streaming",
435
+ error=e,
436
+ )
437
+ await ws.close(code=1011, reason="Error during audio streaming")
438
+ raise
309
439
 
310
440
  return blueprint
311
441
 
@@ -1,7 +1,7 @@
1
1
  import importlib.resources
2
2
  import math
3
3
  from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Text, Tuple
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple
5
5
 
6
6
  import structlog
7
7
  import tiktoken
@@ -18,7 +18,6 @@ from rasa.core.constants import (
18
18
  UTTER_SOURCE_METADATA_KEY,
19
19
  )
20
20
  from rasa.core.policies.policy import Policy, PolicyPrediction, SupportedData
21
- from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
22
21
  from rasa.dialogue_understanding.stack.frames import (
23
22
  ChitChatStackFrame,
24
23
  DialogueStackFrame,
@@ -38,10 +37,9 @@ from rasa.shared.constants import (
38
37
  OPENAI_PROVIDER,
39
38
  PROMPT_CONFIG_KEY,
40
39
  PROVIDER_CONFIG_KEY,
41
- REQUIRED_SLOTS_KEY,
42
40
  TIMEOUT_CONFIG_KEY,
43
41
  )
44
- from rasa.shared.core.constants import ACTION_LISTEN_NAME, ACTION_TRIGGER_CHITCHAT
42
+ from rasa.shared.core.constants import ACTION_LISTEN_NAME
45
43
  from rasa.shared.core.domain import KEY_RESPONSES_TEXT, Domain
46
44
  from rasa.shared.core.events import (
47
45
  ActionExecuted,
@@ -51,6 +49,7 @@ from rasa.shared.core.events import (
51
49
  )
52
50
  from rasa.shared.core.flows import FlowsList
53
51
  from rasa.shared.core.generator import TrackerWithCachedStates
52
+ from rasa.shared.core.policies.utils import filter_responses_for_intentless_policy
54
53
  from rasa.shared.core.trackers import DialogueStateTracker
55
54
  from rasa.shared.exceptions import FileIOException, RasaCoreException
56
55
  from rasa.shared.nlu.constants import PREDICTED_CONFIDENCE_KEY
@@ -146,59 +145,6 @@ class Conversation:
146
145
  interactions: List[Interaction] = field(default_factory=list)
147
146
 
148
147
 
149
- def collect_form_responses(forms: Forms) -> Set[Text]:
150
- """Collect responses that belong the requested slots in forms.
151
-
152
- Args:
153
- forms: the forms from the domain
154
- Returns:
155
- all utterances used in forms
156
- """
157
- form_responses = set()
158
- for _, form_info in forms.data.items():
159
- for required_slot in form_info.get(REQUIRED_SLOTS_KEY, []):
160
- form_responses.add(f"utter_ask_{required_slot}")
161
- return form_responses
162
-
163
-
164
- def filter_responses(responses: Responses, forms: Forms, flows: FlowsList) -> Responses:
165
- """Filters out responses that are unwanted for the intentless policy.
166
-
167
- This includes utterances used in flows and forms.
168
-
169
- Args:
170
- responses: the responses from the domain
171
- forms: the forms from the domain
172
- flows: all flows
173
- Returns:
174
- The remaining, relevant responses for the intentless policy.
175
- """
176
- form_responses = collect_form_responses(forms)
177
- flow_responses = flows.utterances
178
- combined_responses = form_responses | flow_responses
179
- filtered_responses = {
180
- name: variants
181
- for name, variants in responses.data.items()
182
- if name not in combined_responses
183
- }
184
-
185
- pattern_chitchat = flows.flow_by_id(FLOW_PATTERN_CHITCHAT)
186
-
187
- # The following condition is highly unlikely, but mypy requires the case
188
- # of pattern_chitchat == None to be addressed
189
- if not pattern_chitchat:
190
- return Responses(data=filtered_responses)
191
-
192
- # if action_trigger_chitchat, filter out "utter_free_chitchat_response"
193
- has_action_trigger_chitchat = pattern_chitchat.has_action_step(
194
- ACTION_TRIGGER_CHITCHAT
195
- )
196
- if has_action_trigger_chitchat:
197
- filtered_responses.pop("utter_free_chitchat_response", None)
198
-
199
- return Responses(data=filtered_responses)
200
-
201
-
202
148
  def action_from_response(
203
149
  text: Optional[str], responses: Dict[Text, List[Dict[Text, Any]]]
204
150
  ) -> Optional[str]:
@@ -512,7 +458,9 @@ class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
512
458
  # Perform health checks of both LLM and embeddings client configs
513
459
  self._perform_health_checks(self.config, "intentless_policy.train")
514
460
 
515
- responses = filter_responses(responses, forms, flows or FlowsList([]))
461
+ responses = filter_responses_for_intentless_policy(
462
+ responses, forms, flows or FlowsList([])
463
+ )
516
464
  telemetry.track_intentless_policy_train()
517
465
  response_texts = [r for r in extract_ai_response_examples(responses.data)]
518
466
 
@@ -947,7 +895,6 @@ class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
947
895
  **kwargs: Any,
948
896
  ) -> "IntentlessPolicy":
949
897
  """Loads a trained policy (see parent class for full docstring)."""
950
-
951
898
  # Perform health checks of both LLM and embeddings client configs
952
899
  cls._perform_health_checks(config, "intentless_policy.load")
953
900
 
@@ -0,0 +1,9 @@
1
+ import json
2
+
3
+
4
+ def to_json_escaped_string(s: str) -> str:
5
+ """
6
+ Serializes the input string using JSON encoding to escape special characters
7
+ like newlines (\\n), tabs (\\t), and quotes.
8
+ """
9
+ return json.dumps(s, ensure_ascii=False)
@@ -33,3 +33,7 @@ LLM_BASED_COMMAND_GENERATOR_CONFIG_FILE = "config.json"
33
33
 
34
34
  MODEL_NAME_GPT_4O_2024_11_20 = "gpt-4o-2024-11-20"
35
35
  MODEL_NAME_CLAUDE_3_5_SONNET_20240620 = "claude-3-5-sonnet-20240620"
36
+
37
+ # JINJA template filters
38
+
39
+ TO_JSON_ESCAPED_STRING_JINJA_FILTER = "to_json_escaped_string"
@@ -3,7 +3,7 @@ from functools import lru_cache
3
3
  from typing import Any, Dict, List, Optional, Set, Text, Tuple, Union
4
4
 
5
5
  import structlog
6
- from jinja2 import Template
6
+ from jinja2 import Environment, Template, select_autoescape
7
7
 
8
8
  import rasa.dialogue_understanding.generator.utils
9
9
  import rasa.shared.utils.io
@@ -17,12 +17,14 @@ from rasa.dialogue_understanding.commands.handle_digressions_command import (
17
17
  )
18
18
  from rasa.dialogue_understanding.constants import KEY_MINIMIZE_NUM_CALLS
19
19
  from rasa.dialogue_understanding.generator import CommandGenerator
20
+ from rasa.dialogue_understanding.generator._jinja_filters import to_json_escaped_string
20
21
  from rasa.dialogue_understanding.generator.constants import (
21
22
  DEFAULT_LLM_CONFIG,
22
23
  FLOW_RETRIEVAL_ACTIVE_KEY,
23
24
  FLOW_RETRIEVAL_FLOW_THRESHOLD,
24
25
  FLOW_RETRIEVAL_KEY,
25
26
  LLM_CONFIG_KEY,
27
+ TO_JSON_ESCAPED_STRING_JINJA_FILTER,
26
28
  )
27
29
  from rasa.dialogue_understanding.generator.flow_retrieval import FlowRetrieval
28
30
  from rasa.dialogue_understanding.stack.utils import top_flow_frame
@@ -226,12 +228,26 @@ class LLMBasedCommandGenerator(
226
228
 
227
229
  @lru_cache
228
230
  def compile_template(self, template: str) -> Template:
229
- """Compile the prompt template.
230
-
231
+ """
232
+ Compile the prompt template and register custom filters.
231
233
  Compiling the template is an expensive operation,
232
234
  so we cache the result.
233
235
  """
234
- return Template(template)
236
+ # Create an environment
237
+ # Autoescaping disabled explicitly for LLM prompt templates rendered from
238
+
239
+ # strings (safe, not HTML)
240
+ env = Environment(
241
+ autoescape=select_autoescape(
242
+ disabled_extensions=["jinja2"], default_for_string=False, default=True
243
+ )
244
+ )
245
+
246
+ # Register filters
247
+ env.filters[TO_JSON_ESCAPED_STRING_JINJA_FILTER] = to_json_escaped_string
248
+
249
+ # Return the template which can leverage registered filters
250
+ return env.from_string(template)
235
251
 
236
252
  @classmethod
237
253
  def load_prompt_template_from_model_storage(
@@ -140,7 +140,7 @@ class NLUCommandAdapter(GraphComponent, CommandGenerator):
140
140
 
141
141
  if commands:
142
142
  commands = clean_up_commands(
143
- commands, tracker, flows, self._execution_context
143
+ commands, tracker, flows, self._execution_context, domain
144
144
  )
145
145
  log_llm(
146
146
  logger=structlogger,
@@ -33,7 +33,7 @@ Your task is to analyze the current conversation context and generate a list of
33
33
  ## Available Flows and Slots
34
34
  Use the following structured data:
35
35
  ```json
36
- {"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":"{{ flow.description }}"{% if flow.slots %},"slots":[{% for slot in flow.slots %}{"name":"{{ slot.name }}"{% if slot.description %},"description":"{{ slot.description }}"{% endif %}{% if slot.allowed_values %},"allowed_values":{{ slot.allowed_values }}{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
36
+ {"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":{{ flow.description | to_json_escaped_string }}{% if flow.slots %},"slots":[{% for slot in flow.slots %}{"name":"{{ slot.name }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":{{ slot.allowed_values }}{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
37
37
  ```
38
38
 
39
39
  --
@@ -41,7 +41,7 @@ Use the following structured data:
41
41
  ## Current State
42
42
  {% if current_flow != None %}Use the following structured data:
43
43
  ```json
44
- {"active_flow":"{{ current_flow }}","current_step":{"requested_slot":"{{ current_slot }}","requested_slot_description":"{{ current_slot_description }}"},"slots":[{% for slot in flow_slots %}{"name":"{{ slot.name }}","value":"{{ slot.value }}","type":"{{ slot.type }}"{% if slot.description %},"description":"{{ slot.description }}"{% endif %}{% if slot.allowed_values %},"allowed_values":"{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
44
+ {"active_flow":"{{ current_flow }}","current_step":{"requested_slot":"{{ current_slot }}","requested_slot_description":{{ current_slot_description | to_json_escaped_string }}},"slots":[{% for slot in flow_slots %}{"name":"{{ slot.name }}","value":"{{ slot.value }}","type":"{{ slot.type }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":"{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
45
45
  ```{% else %}
46
46
  You are currently not inside any flow.{% endif %}
47
47
 
@@ -6,7 +6,7 @@ Your task is to analyze the current conversation context and generate a list of
6
6
  ## Available Flows and Slots
7
7
  Use the following structured data:
8
8
  ```json
9
- {"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":"{{ flow.description }}"{% if flow.slots %},"slots":[{% for slot in flow.slots %}{"name":"{{ slot.name }}"{% if slot.description %},"description":"{{ slot.description }}"{% endif %}{% if slot.allowed_values %},"allowed_values":{{ slot.allowed_values }}{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
9
+ {"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":{{ flow.description | to_json_escaped_string }}{% if flow.slots %},"slots":[{% for slot in flow.slots %}{"name":"{{ slot.name }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":{{ slot.allowed_values }}{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
10
10
  ```
11
11
 
12
12
  ---
@@ -40,7 +40,7 @@ Use the following structured data:
40
40
  ## Current State
41
41
  {% if current_flow != None %}Use the following structured data:
42
42
  ```json
43
- {"active_flow":"{{ current_flow }}","current_step":{"requested_slot":"{{ current_slot }}","requested_slot_description":"{{ current_slot_description }}"},"slots":[{% for slot in flow_slots %}{"name":"{{ slot.name }}","value":"{{ slot.value }}","type":"{{ slot.type }}"{% if slot.description %},"description":"{{ slot.description }}"{% endif %}{% if slot.allowed_values %},"allowed_values":"{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
43
+ {"active_flow":"{{ current_flow }}","current_step":{"requested_slot":"{{ current_slot }}","requested_slot_description":{{ current_slot_description | to_json_escaped_string }}},"slots":[{% for slot in flow_slots %}{"name":"{{ slot.name }}","value":"{{ slot.value }}","type":"{{ slot.type }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":"{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
44
44
  ```{% else %}
45
45
  You are currently not inside any flow.{% endif %}
46
46
 
@@ -54,9 +54,11 @@ from rasa.shared.core.constants import (
54
54
  FLOW_HASHES_SLOT,
55
55
  SlotMappingType,
56
56
  )
57
+ from rasa.shared.core.domain import Domain
57
58
  from rasa.shared.core.events import Event, SlotSet
58
59
  from rasa.shared.core.flows import FlowsList
59
60
  from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
61
+ from rasa.shared.core.policies.utils import contains_intentless_policy_responses
60
62
  from rasa.shared.core.slot_mappings import SlotMapping
61
63
  from rasa.shared.core.slots import Slot
62
64
  from rasa.shared.core.trackers import DialogueStateTracker
@@ -197,6 +199,7 @@ def execute_commands(
197
199
  all_flows: FlowsList,
198
200
  execution_context: ExecutionContext,
199
201
  story_graph: Optional[StoryGraph] = None,
202
+ domain: Optional[Domain] = None,
200
203
  ) -> List[Event]:
201
204
  """Executes a list of commands.
202
205
 
@@ -206,6 +209,7 @@ def execute_commands(
206
209
  all_flows: All flows.
207
210
  execution_context: Information about the single graph run.
208
211
  story_graph: StoryGraph object with stories available for training.
212
+ domain: The domain of the bot.
209
213
 
210
214
  Returns:
211
215
  A list of the events that were created.
@@ -214,7 +218,7 @@ def execute_commands(
214
218
  original_tracker = tracker.copy()
215
219
 
216
220
  commands = clean_up_commands(
217
- commands, tracker, all_flows, execution_context, story_graph
221
+ commands, tracker, all_flows, execution_context, story_graph, domain
218
222
  )
219
223
 
220
224
  updated_flows = find_updated_flows(tracker, all_flows)
@@ -381,6 +385,7 @@ def clean_up_commands(
381
385
  all_flows: FlowsList,
382
386
  execution_context: ExecutionContext,
383
387
  story_graph: Optional[StoryGraph] = None,
388
+ domain: Optional[Domain] = None,
384
389
  ) -> List[Command]:
385
390
  """Clean up a list of commands.
386
391
 
@@ -396,10 +401,13 @@ def clean_up_commands(
396
401
  all_flows: All flows.
397
402
  execution_context: Information about a single graph run.
398
403
  story_graph: StoryGraph object with stories available for training.
404
+ domain: The domain of the bot.
399
405
 
400
406
  Returns:
401
407
  The cleaned up commands.
402
408
  """
409
+ domain = domain if domain else Domain.empty()
410
+
403
411
  slots_so_far, active_flow = filled_slots_for_active_flow(tracker, all_flows)
404
412
 
405
413
  clean_commands: List[Command] = []
@@ -465,7 +473,12 @@ def clean_up_commands(
465
473
  # handle chitchat command differently from other free-form answer commands
466
474
  elif isinstance(command, ChitChatAnswerCommand):
467
475
  clean_commands = clean_up_chitchat_command(
468
- clean_commands, command, all_flows, execution_context, story_graph
476
+ clean_commands,
477
+ command,
478
+ all_flows,
479
+ execution_context,
480
+ domain,
481
+ story_graph,
469
482
  )
470
483
 
471
484
  elif isinstance(command, FreeFormAnswerCommand):
@@ -708,6 +721,7 @@ def clean_up_chitchat_command(
708
721
  command: ChitChatAnswerCommand,
709
722
  flows: FlowsList,
710
723
  execution_context: ExecutionContext,
724
+ domain: Domain,
711
725
  story_graph: Optional[StoryGraph] = None,
712
726
  ) -> List[Command]:
713
727
  """Clean up a chitchat answer command.
@@ -721,6 +735,8 @@ def clean_up_chitchat_command(
721
735
  flows: All flows.
722
736
  execution_context: Information about a single graph run.
723
737
  story_graph: StoryGraph object with stories available for training.
738
+ domain: The domain of the bot.
739
+
724
740
  Returns:
725
741
  The cleaned up commands.
726
742
  """
@@ -746,10 +762,9 @@ def clean_up_chitchat_command(
746
762
  )
747
763
  defines_intentless_policy = execution_context.has_node(IntentlessPolicy)
748
764
 
749
- has_e2e_stories = True if (story_graph and story_graph.has_e2e_stories()) else False
750
-
751
765
  if (has_action_trigger_chitchat and not defines_intentless_policy) or (
752
- defines_intentless_policy and not has_e2e_stories
766
+ defines_intentless_policy
767
+ and not contains_intentless_policy_responses(flows, domain, story_graph)
753
768
  ):
754
769
  resulting_commands.insert(
755
770
  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,7 +6,7 @@ Each question variation should be a question that the input answer is attempting
6
6
  Follow these steps to complete the task:
7
7
 
8
8
  1. Generate {{ num_variations }} question variations that the input answer is attempting to answer.
9
- 3. Compile all the question variations into a JSON object.
9
+ 2. Compile all the question variations into a JSON object.
10
10
 
11
11
  ### JSON Output
12
12
 
rasa/engine/validation.py CHANGED
@@ -86,7 +86,9 @@ from rasa.shared.constants import (
86
86
  from rasa.shared.core.constants import ACTION_RESET_ROUTING, ACTION_TRIGGER_CHITCHAT
87
87
  from rasa.shared.core.domain import Domain
88
88
  from rasa.shared.core.flows import Flow, FlowsList
89
+ from rasa.shared.core.policies.utils import contains_intentless_policy_responses
89
90
  from rasa.shared.core.slots import Slot
91
+ from rasa.shared.core.training_data.structures import StoryGraph
90
92
  from rasa.shared.exceptions import RasaException
91
93
  from rasa.shared.nlu.training_data.message import Message
92
94
  from rasa.shared.utils.common import display_research_study_prompt
@@ -642,11 +644,18 @@ def _recursively_check_required_components(
642
644
 
643
645
 
644
646
  def validate_flow_component_dependencies(
645
- flows: FlowsList, model_configuration: GraphModelConfiguration
647
+ flows: FlowsList,
648
+ domain: Domain,
649
+ story_graph: StoryGraph,
650
+ model_configuration: GraphModelConfiguration,
646
651
  ) -> None:
647
652
  if (pattern_chitchat := flows.flow_by_id(FLOW_PATTERN_CHITCHAT)) is not None:
648
653
  _validate_chitchat_dependencies(pattern_chitchat, model_configuration)
649
654
 
655
+ _validate_intentless_policy_responses(
656
+ flows, domain, story_graph, model_configuration
657
+ )
658
+
650
659
 
651
660
  def _validate_chitchat_dependencies(
652
661
  pattern_chitchat: Flow, model_configuration: GraphModelConfiguration
@@ -674,6 +683,32 @@ def _validate_chitchat_dependencies(
674
683
  )
675
684
 
676
685
 
686
+ def _validate_intentless_policy_responses(
687
+ flows: FlowsList,
688
+ domain: Domain,
689
+ story_graph: StoryGraph,
690
+ model_configuration: GraphModelConfiguration,
691
+ ) -> None:
692
+ """If IntentlessPolicy is configured, validate that it has responses to use:
693
+ either responses from the domain that are not part of any flow, or from
694
+ end-to-end stories.
695
+ """
696
+ if not model_configuration.predict_schema.has_node(IntentlessPolicy):
697
+ return
698
+
699
+ if not contains_intentless_policy_responses(flows, domain, story_graph):
700
+ structlogger.error(
701
+ "validation.intentless_policy.no_applicable_responses_found",
702
+ event_info=(
703
+ "IntentlessPolicy is configured, but no applicable responses are "
704
+ "found. Please make sure that there are responses defined in the "
705
+ "domain that are not part of any flow, or that there are "
706
+ "end-to-end stories in the training data."
707
+ ),
708
+ )
709
+ sys.exit(1)
710
+
711
+
677
712
  def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
678
713
  """Extracts the index of a component of the given class in the schema.
679
714
  This function assumes that each component's node name is stored in a way
rasa/model_training.py CHANGED
@@ -315,6 +315,7 @@ async def _train_graph(
315
315
  )
316
316
  flows = file_importer.get_flows()
317
317
  domain = file_importer.get_domain()
318
+ story_graph = file_importer.get_stories()
318
319
  model_configuration = recipe.graph_config_for_recipe(
319
320
  config,
320
321
  kwargs,
@@ -330,7 +331,7 @@ async def _train_graph(
330
331
  config
331
332
  )
332
333
  rasa.engine.validation.validate_flow_component_dependencies(
333
- flows, model_configuration
334
+ flows, domain, story_graph, model_configuration
334
335
  )
335
336
  rasa.engine.validation.validate_command_generator_setup(model_configuration)
336
337
 
rasa/shared/constants.py CHANGED
@@ -99,6 +99,8 @@ UTTER_ASK_PREFIX = "utter_ask_"
99
99
  ACTION_ASK_PREFIX = "action_ask_"
100
100
  FLOW_PREFIX = "flow_"
101
101
 
102
+ UTTER_FREE_CHITCHAT_RESPONSE = "utter_free_chitchat_response"
103
+
102
104
  ASSISTANT_ID_KEY = "assistant_id"
103
105
  ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
104
106
 
@@ -1678,6 +1678,14 @@ class Domain:
1678
1678
  """Write domain to a file."""
1679
1679
  as_yaml = self.as_yaml()
1680
1680
  rasa.shared.utils.io.write_text_file(as_yaml, filename)
1681
+ # run the check again on the written domain to catch any errors
1682
+ # that may have been missed in the user defined domain files
1683
+ structlogger.info(
1684
+ "domain.persist.domain_written_to_file",
1685
+ event_info="The entire domain content has been written to file.",
1686
+ filename=filename,
1687
+ )
1688
+ Domain.is_domain_file(filename)
1681
1689
 
1682
1690
  def as_yaml(self) -> Text:
1683
1691
  """Dump the `Domain` object as a YAML string.
@@ -1972,17 +1980,18 @@ class Domain:
1972
1980
 
1973
1981
  try:
1974
1982
  content = read_yaml_file(filename, expand_env_vars=cls.expand_env_vars)
1975
- except (RasaException, YamlSyntaxException):
1976
- structlogger.warning(
1983
+ except (RasaException, YamlSyntaxException) as error:
1984
+ structlogger.error(
1977
1985
  "domain.cannot_load_domain_file",
1978
1986
  file=filename,
1987
+ error=error,
1979
1988
  event_info=(
1980
1989
  f"The file {filename} could not be loaded as domain file. "
1981
1990
  f"You can use https://yamlchecker.com/ to validate "
1982
1991
  f"the YAML syntax of your file."
1983
1992
  ),
1984
1993
  )
1985
- return False
1994
+ raise RasaException(f"Domain could not be loaded: {error}")
1986
1995
 
1987
1996
  return any(key in content for key in ALL_DOMAIN_KEYS)
1988
1997
 
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
@@ -115,6 +115,18 @@ class SlotMapping(BaseModel):
115
115
  )
116
116
  data_copy[KEY_RUN_ACTION_EVERY_TURN] = deprecated_action
117
117
 
118
+ structlogger.warning(
119
+ "slot_mapping.deprecated_action_key_replaced_with_run_action_every_turn",
120
+ slot_name=slot_name,
121
+ event_info=f"The `{KEY_ACTION}` key in slot mappings "
122
+ f"has been replaced with "
123
+ f"the `{KEY_RUN_ACTION_EVERY_TURN}` key. "
124
+ f"This will result in the custom action "
125
+ f"being executed at every conversation turn "
126
+ f"automatically. Remove the key "
127
+ f"to avoid this behavior.",
128
+ )
129
+
118
130
  run_action_every_turn = data_copy.pop(KEY_RUN_ACTION_EVERY_TURN, None)
119
131
 
120
132
  coexistence_system = data_copy.pop(KEY_COEXISTENCE_SYSTEM, None)
@@ -454,6 +454,7 @@ def extract_attrs_for_execute_commands(
454
454
  all_flows: FlowsList,
455
455
  execution_context: ExecutionContext,
456
456
  story_graph: Optional[StoryGraph] = None,
457
+ domain: Optional[Domain] = None,
457
458
  ) -> Dict[str, Any]:
458
459
  return {
459
460
  "number_of_events": len(tracker.events),
@@ -497,6 +498,7 @@ def extract_attrs_for_clean_up_commands(
497
498
  all_flows: FlowsList,
498
499
  execution_context: ExecutionContext,
499
500
  story_graph: Optional[StoryGraph] = None,
501
+ domain: Optional[Domain] = None,
500
502
  ) -> Dict[str, Any]:
501
503
  commands_list = []
502
504
 
rasa/version.py CHANGED
@@ -1,3 +1,4 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.12.4"
3
+
4
+ __version__ = "3.12.6.dev1"
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.12.4
3
+ Version: 3.12.6.dev1
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
@@ -86,7 +85,6 @@ Requires-Dist: protobuf (>=4.23.3,<4.25.4)
86
85
  Requires-Dist: psutil (>=5.9.5,<6.0.0)
87
86
  Requires-Dist: psycopg2-binary (>=2.9.9,<2.10.0)
88
87
  Requires-Dist: pycountry (>=22.3.5,<23.0.0)
89
- Requires-Dist: pydantic (>=2.0,<3.0)
90
88
  Requires-Dist: pydot (>=1.4,<1.5)
91
89
  Requires-Dist: pykwalify (>=1.8,<1.9)
92
90
  Requires-Dist: pymilvus (>=2.4.1,<2.4.2)
@@ -118,7 +116,6 @@ Requires-Dist: scikit-learn (>=1.5.1,<1.6.0)
118
116
  Requires-Dist: scipy (>=1.13.1,<1.14.0)
119
117
  Requires-Dist: sentencepiece[sentencepiece] (>=0.1.99,<0.2.0) ; extra == "transformers" or extra == "full"
120
118
  Requires-Dist: sentry-sdk (>=1.14.0,<1.15.0)
121
- Requires-Dist: setuptools (>=70.0.0,<70.1.0)
122
119
  Requires-Dist: sklearn-crfsuite (>=0.3.6,<0.4.0)
123
120
  Requires-Dist: skops (>=0.10.0,<0.11.0)
124
121
  Requires-Dist: slack-sdk (>=3.27.1,<3.28.0)
@@ -135,7 +132,7 @@ Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "darwin"
135
132
  Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "linux"
136
133
  Requires-Dist: tensorflow-macos (==2.14.1) ; sys_platform == "darwin" and platform_machine == "arm64"
137
134
  Requires-Dist: tensorflow-metal (==1.1.0) ; (sys_platform == "darwin" and platform_machine == "arm64") and (extra == "metal")
138
- Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and (platform_machine != "arm64" and platform_machine != "aarch64")
135
+ Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and platform_machine != "arm64" and platform_machine != "aarch64"
139
136
  Requires-Dist: tensorflow_hub (>=0.13.0,<0.14.0)
140
137
  Requires-Dist: terminaltables (>=3.1.10,<3.2.0)
141
138
  Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
@@ -148,8 +145,8 @@ Requires-Dist: typing-utils (>=0.1.0,<0.2.0)
148
145
  Requires-Dist: ujson (>=5.8,<6.0)
149
146
  Requires-Dist: webexteamssdk (>=1.6.1,<1.7.0)
150
147
  Requires-Dist: websockets (>=10.4,<11.0)
151
- Requires-Dist: wheel (>=0.40.0)
152
148
  Project-URL: Documentation, https://rasa.com/docs
149
+ Project-URL: Homepage, https://rasa.com
153
150
  Project-URL: Repository, https://github.com/rasahq/rasa
154
151
  Description-Content-Type: text/markdown
155
152
 
@@ -1,4 +1,3 @@
1
- README.md,sha256=rn81McEFcq6MM6i5ZVs-MV7HQd4ffBVtBeVV2DvF7Bo,3175
2
1
  rasa/__init__.py,sha256=YXG8RzVxiSJ__v-AewtV453YoCbmzWlHsU_4S0O2XpE,206
3
2
  rasa/__main__.py,sha256=OmUXcaA9l7KR_eSYCwaCSetuczxjrcN2taNnZ2ZUTbA,6472
4
3
  rasa/anonymization/__init__.py,sha256=Z-ZUW2ofZGfI6ysjYIS7U0JL4JSzDNOkHiiXK488Zik,86
@@ -269,7 +268,7 @@ rasa/core/channels/telegram.py,sha256=TKVknsk3U9tYeY1a8bzlhqkltWmZfGSOvrcmwa9qoz
269
268
  rasa/core/channels/twilio.py,sha256=2BTQpyx0b0yPpc0A2BHYfxLPgodrLGLs8nq6i3lVGAM,5906
270
269
  rasa/core/channels/vier_cvg.py,sha256=GkrWKu7NRMFtLMyYp-kQ2taWAc_keAwhYrkVPW56iaU,13544
271
270
  rasa/core/channels/voice_ready/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
272
- rasa/core/channels/voice_ready/audiocodes.py,sha256=Ysh_ZscHnM2phNhkhgCmm9KUYu2hAWrkjJmTyon6i6o,19543
271
+ rasa/core/channels/voice_ready/audiocodes.py,sha256=s9tA6Tv2Ywro0YP_XhoKO7Q92g5MbPPzw6GdFij4cwk,19833
273
272
  rasa/core/channels/voice_ready/jambonz.py,sha256=r7O8k_X934lQe0fzY7R0z_hMeX5qMN663bTugQ1-8eQ,4154
274
273
  rasa/core/channels/voice_ready/jambonz_protocol.py,sha256=idWArI4SRr4fjyZx3VIUoua_cbLwpvw4e5VeHyQjE8E,12975
275
274
  rasa/core/channels/voice_ready/twilio_voice.py,sha256=5N5dQ2l_u8CC9J16USgufl6MB1bJziCky7VT58MPt68,14520
@@ -281,10 +280,10 @@ rasa/core/channels/voice_stream/asr/asr_event.py,sha256=skPwrkRrcsptmeWXu9q68i4B
281
280
  rasa/core/channels/voice_stream/asr/azure.py,sha256=uqg2xAmGfP8N9pts_AT6KxobiuQIqRy1lkyU7vqC564,5845
282
281
  rasa/core/channels/voice_stream/asr/deepgram.py,sha256=9cIqRuv9gWzOfEKxeDbhijGoT8EPUV7Oo493WXaHlBo,5682
283
282
  rasa/core/channels/voice_stream/audio_bytes.py,sha256=3V0QQplPD-kVfebaaeVcKgV7pwIJyjnTenujVD3y3sY,340
284
- rasa/core/channels/voice_stream/audiocodes.py,sha256=sGFF_ixate9LlCIl245zVd9lx65n1euPe2k9kuxVgG0,10950
283
+ rasa/core/channels/voice_stream/audiocodes.py,sha256=WVAd5ksO97y7a6Wvv6PqQKQVgS1_IdRXeDIjnl6IAkY,12498
285
284
  rasa/core/channels/voice_stream/browser_audio.py,sha256=fDwp-yaalik8R92EOJHsgHMuNAg9yoeGWVRGMCH2lJQ,3939
286
285
  rasa/core/channels/voice_stream/call_state.py,sha256=fbwVbT0ddE7AjTYjx-Mq5jBMEGXanbug5wlBwstaews,899
287
- rasa/core/channels/voice_stream/genesys.py,sha256=-XznlXrSs4q7pXXDJICI5GEtu3aCzejvHNwtYtcoGM8,11957
286
+ rasa/core/channels/voice_stream/genesys.py,sha256=EyZ4G3gfiQ5HXP6jslTjXRBYVEhpyO8nK5r6znQtHtE,16965
288
287
  rasa/core/channels/voice_stream/tts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
289
288
  rasa/core/channels/voice_stream/tts/azure.py,sha256=Fj9vLg-8d6aCoDcycDMG0oIPl5gw7Nhb8MXb-wBvLhE,4221
290
289
  rasa/core/channels/voice_stream/tts/cartesia.py,sha256=cH2eHicZ_NCWtDH-cn9Chq8SSm-1agJRy-ieDJCVlD4,5407
@@ -336,7 +335,7 @@ rasa/core/policies/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
336
335
  rasa/core/policies/flows/flow_exceptions.py,sha256=_FQuN-cerQDM1pivce9bz4zylh5UYkljvYS1gjDukHI,1527
337
336
  rasa/core/policies/flows/flow_executor.py,sha256=1KJhBovD9INHVF7PQD4N7CH46JFfPrsy7QXnnGAPlNU,26938
338
337
  rasa/core/policies/flows/flow_step_result.py,sha256=agjPrD6lahGSe2ViO5peBeoMdI9ngVGRSgtytgxmJmg,1360
339
- rasa/core/policies/intentless_policy.py,sha256=p9e54sSjTOGAFxLbPdF0jspQNETmtBvg-RXQNPviIbE,37898
338
+ rasa/core/policies/intentless_policy.py,sha256=rSETeSDC3jodKvVeNeBc5OBptpSCsEYJdeJEB0b2p3U,36091
340
339
  rasa/core/policies/intentless_prompt_template.jinja2,sha256=KhIL3cruMmkxhrs5oVbqgSvK6ZiN_6TQ_jXrgtEB-ZY,677
341
340
  rasa/core/policies/memoization.py,sha256=CX2d3yP7FehSMW92Wi9NYLZei7tBzoT3T6yybu-Nb5s,19377
342
341
  rasa/core/policies/policy.py,sha256=5SUnPajSTSf8PzB1-jFbQPtsvR-zLN-xkjeotWOxuJc,27432
@@ -396,22 +395,23 @@ rasa/dialogue_understanding/commands/user_silence_command.py,sha256=DQjRfZk09sV1
396
395
  rasa/dialogue_understanding/commands/utils.py,sha256=lyl8FSdR2kQogqdjX2NSpQVQ9D2FZpwYUG6z4yFIMlU,4057
397
396
  rasa/dialogue_understanding/constants.py,sha256=_kB0edGV23uvhujlF193N2jk6YG0R6LC599YDX5B5vo,129
398
397
  rasa/dialogue_understanding/generator/__init__.py,sha256=pBm0o6pnJA_0W0UOrGuVsiG4hsTNH_n5GLrz8BYQHM8,830
398
+ rasa/dialogue_understanding/generator/_jinja_filters.py,sha256=KuK7nGKvKzKJz6Wg3AmrLFvzneGgIyeK825MCE379wc,248
399
399
  rasa/dialogue_understanding/generator/command_generator.py,sha256=QvYHF3w_WgyItMySUtf0B2Qmb_7SEOLONmQXdLseIt8,13184
400
400
  rasa/dialogue_understanding/generator/command_parser.py,sha256=wf6FSgqBw5F0legg06SqKlzajIN6sc_Cov2lFY_O9MI,8109
401
- rasa/dialogue_understanding/generator/constants.py,sha256=nA184YgNRaoA9Q0XlLp7VKxGCX4nN_b3zLyDaL22rQw,1018
401
+ rasa/dialogue_understanding/generator/constants.py,sha256=PuUckBGUZ-Tu31B0cs8yxN99BDW3PGoExZa-BlIL5v8,1108
402
402
  rasa/dialogue_understanding/generator/flow_document_template.jinja2,sha256=f4H6vVd-_nX_RtutMh1xD3ZQE_J2OyuPHAtiltfiAPY,253
403
403
  rasa/dialogue_understanding/generator/flow_retrieval.py,sha256=wlGnMj17-X1-siQmdSvOd7K61sRzBf82MQEL2pqDQMI,17891
404
- rasa/dialogue_understanding/generator/llm_based_command_generator.py,sha256=CksE7iUchYuKwCJBYhLhEaf4kMLtAOyUFBJOxYj_FFU,23237
404
+ rasa/dialogue_understanding/generator/llm_based_command_generator.py,sha256=7fjjA6aPKmHd3Qml0AqEhuqIySXzVjhpYsfFcN7sPws,23950
405
405
  rasa/dialogue_understanding/generator/llm_command_generator.py,sha256=z7jhIJ3W_5GFH-p15kVoWbigMIoY8fIJjc_j_uX7yxw,2581
406
406
  rasa/dialogue_understanding/generator/multi_step/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
407
407
  rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2,sha256=Y0m673tAML3cFPaLM-urMXDsBYUUcXIw9YUpkAhGUuA,2933
408
408
  rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2,sha256=8l93_QBKBYnqLICVdiTu5ejZDE8F36BU8-qwba0px44,1927
409
409
  rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py,sha256=kvVbUibV-OgiaLhgnmbA7UWKXKsN7TN_OjmLJfI49M8,31969
410
- rasa/dialogue_understanding/generator/nlu_command_adapter.py,sha256=28QdoZ330DL5X-SdUQASjsmyf9KIY3GGHbrl2xEeZMU,10868
410
+ rasa/dialogue_understanding/generator/nlu_command_adapter.py,sha256=cisxLlPVQXgbWMAz9xSxBvrOz4HO-f0G3CFVjJ2wt-g,10876
411
411
  rasa/dialogue_understanding/generator/prompt_templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
412
412
  rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2,sha256=nMayu-heJYH1QmcL1cFmXb8SeiJzfdDR_9Oy5IRUXsM,3937
413
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2,sha256=XKRIUuBGBacmj7bGAbOfHwPUPeSOdqk64vBTiLy4sR8,3716
414
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2,sha256=pUiNfYUdPJksFtn0uIpTg-B9MqskpFLrpiEaV5HzOgs,3528
413
+ rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2,sha256=z-cnFVfIE_kEnY1o52YE2CdCWwgYTv7R3xVxsjXWlnw,3808
414
+ rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2,sha256=4076ARsy0E0iADBX6li19IoM3F4F-2wK3bL6UEOvCdo,3620
415
415
  rasa/dialogue_understanding/generator/single_step/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
416
416
  rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py,sha256=jRnc_vp95kR5qkEHyGnq3VGuMxdho88a0KZis96NbWU,21735
417
417
  rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py,sha256=cvWsl-hYUgZ_tIQmWjMM1RQwsgRTlZ_osfLaUQiBk-U,4543
@@ -438,8 +438,8 @@ rasa/dialogue_understanding/patterns/skip_question.py,sha256=fJ1MC0WEEtS-BpnGJEf
438
438
  rasa/dialogue_understanding/patterns/user_silence.py,sha256=xP-QMnd-MsybH5z4g01hBv4OLOHcw6m3rc26LQfe2zo,1140
439
439
  rasa/dialogue_understanding/patterns/validate_slot.py,sha256=hqd5AEGT3M3HLNhMwuI9W9kZNCvgU6GyI-2xc2b4kz8,2085
440
440
  rasa/dialogue_understanding/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
441
- rasa/dialogue_understanding/processor/command_processor.py,sha256=-uOr7z4EhIQl1ffD-q2xoTYA0qiFSDArdgdyo7kJHOA,31884
442
- rasa/dialogue_understanding/processor/command_processor_component.py,sha256=9NWJxMibKeaOBLDRT9lcylJr0ki5sQ0hJRtLlKHIlnI,1526
441
+ rasa/dialogue_understanding/processor/command_processor.py,sha256=-x0sS1btKChMRMResArpdZiskbLJABu9JowL6vIBlas,32335
442
+ rasa/dialogue_understanding/processor/command_processor_component.py,sha256=nvp_q-vM2ZEa7sbNMjRhEeuvmCwVWQl1ckTf0UAXuH4,1606
443
443
  rasa/dialogue_understanding/stack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
444
444
  rasa/dialogue_understanding/stack/dialogue_stack.py,sha256=cYV6aQeh0EuOJHODDqK3biqXozYTX8baPgLwHhPxFqs,5244
445
445
  rasa/dialogue_understanding/stack/frames/__init__.py,sha256=wczg4PXtwGlCcRWT4gdtwgO-ZHVDcEYG11qDMe5hRNw,656
@@ -479,7 +479,7 @@ rasa/e2e_test/e2e_test_coverage_report.py,sha256=zO_3hQIuCf4r9YIbQ2_DHM7HCWHe9pZ
479
479
  rasa/e2e_test/e2e_test_result.py,sha256=qVurjFC4cAWIY7rOsc-A-4nIdcnnw98TaK86-bDwI7Y,1649
480
480
  rasa/e2e_test/e2e_test_runner.py,sha256=eXV5DJ0rAVY7FAXYI9aKvYqZXdfsE92y6deEUqUvrTY,47965
481
481
  rasa/e2e_test/e2e_test_schema.yml,sha256=0deWjuKRHNo6e_LSCnUoiw9NLIYf6dj1-zFPl_AqLYA,5632
482
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2,sha256=W8sb_6mDRxuRpyC8hf5jdP6KkdiFj5n7E9O1LDgQFLA,2726
482
+ rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2,sha256=6Ddszg4Y6sIvhH7C1jjEAArpzke48mfCOa2KUQYbNVA,2725
483
483
  rasa/e2e_test/llm_judge_prompts/groundedness_prompt_template.jinja2,sha256=jCgDbZvWn5fncr4zvB5UQSK1VJu9xDQtpY4B8GKtlmA,8226
484
484
  rasa/e2e_test/pykwalify_extensions.py,sha256=OGYKIKYJXd2S0NrWknoQuijyBQaE-oMLkfV_eMRkGSM,1331
485
485
  rasa/e2e_test/stub_custom_action.py,sha256=aGOdZEQVZJpfY5zaHUcG447_tdJCncgD3G85eDUlVj0,2369
@@ -513,7 +513,7 @@ rasa/engine/training/components.py,sha256=Ymz8-JcKm5A9dqPblay11Lxo_AFShkakXlsHQ9
513
513
  rasa/engine/training/fingerprinting.py,sha256=RrJzkhTefKsj2A1S4yAJ4IIUZGganGTcKKdor-FfLjA,2008
514
514
  rasa/engine/training/graph_trainer.py,sha256=jLfJZVn-mDwIOEADnx56Ly67EPf5XMpf_gH5PwRe-7o,10636
515
515
  rasa/engine/training/hooks.py,sha256=dec5yMRNbVIJwtijhESJNlt8lbZb1KJffcBRBajuZes,5469
516
- rasa/engine/validation.py,sha256=9wI7FjW-g1HxzlsxVhb-p7IH3IBGQYydbC7ojIV6Xwc,59505
516
+ rasa/engine/validation.py,sha256=bL9jDZ7VdZgi3eujqUvXHY7WdyOTVJOKYxxs-F-xGzo,60816
517
517
  rasa/env.py,sha256=zLzQMkATVIZj6s4C7RsLLOLT8g6-Q96m5iBaHW_mEA8,480
518
518
  rasa/exceptions.py,sha256=sUcLgF-iGK1CEQkCVar28nzap8hUhaxSJvtKu2jPLFY,2117
519
519
  rasa/graph_components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -534,7 +534,6 @@ rasa/graph_components/validators/default_recipe_validator.py,sha256=iOVoB7zVTKes
534
534
  rasa/graph_components/validators/finetuning_validator.py,sha256=VfCGytnweijKBG8bAqYp7zKZB2aRgi2ZI8R0eou5Ev4,12865
535
535
  rasa/hooks.py,sha256=5ZMrqNz323w56MMY6E8jeZ_YXgRqq8p-yi18S2XOmbo,4061
536
536
  rasa/jupyter.py,sha256=TCYVD4QPQIMmfA6ZwDUBOBTAECwCwbU2XOkosodLO9k,1782
537
- rasa/keys,sha256=2Stg1fstgJ203cOoW1B2gGMY29fhEnjIfTVxKv_fqPo,101
538
537
  rasa/llm_fine_tuning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
539
538
  rasa/llm_fine_tuning/annotation_module.py,sha256=6wBBjGwONVlikp79xAHp5g3rydEhPM6kP1bw1g-maYk,8578
540
539
  rasa/llm_fine_tuning/conversations.py,sha256=QZVaUsfXe5iIE830Bv-_3oo8luhGfHpirvubxzOoEvA,4116
@@ -565,7 +564,7 @@ rasa/model_manager/utils.py,sha256=rS0ST-rJMuZOna90r_Ioz7gOkZ8r8vm4XAhzI0iUZOA,2
565
564
  rasa/model_manager/warm_rasa_process.py,sha256=2vg8gBEUvPrr6C5W-fxtWWSajksrOaT83CTk6S4KCkg,5843
566
565
  rasa/model_service.py,sha256=XXCaiLj2xq58n05W3R1jmTIv-V8f_7PG30kVpRxf71Y,3727
567
566
  rasa/model_testing.py,sha256=eZw7l8Zz3HkH_ZPBurY93HzzudHdoQn8HBnDdZSysAY,14929
568
- rasa/model_training.py,sha256=KhYKlnKdMrWpsOqap8aRczAA0aQps2Wj-Mh0NIEi_N0,21666
567
+ rasa/model_training.py,sha256=1opig8_npw7dLHd8k06ZYUQCrJ61sFIbNHBgvF63yH8,21733
569
568
  rasa/nlu/__init__.py,sha256=D0IYuTK_ZQ_F_9xsy0bXxVCAtU62Fzvp8S7J9tmfI_c,123
570
569
  rasa/nlu/classifiers/__init__.py,sha256=Qvrf7_rfiMxm2Vt2fClb56R3QFExf7WPdFdL-AOvgsk,118
571
570
  rasa/nlu/classifiers/classifier.py,sha256=9fm1mORuFf1vowYIXmqE9yLRKdSC4nGQW7UqNZQipKY,133
@@ -627,12 +626,12 @@ rasa/nlu/utils/spacy_utils.py,sha256=5EnHR-MVAZhGbg2rq8VpOu7I0tagV3ThRTlM0-WO2Cg
627
626
  rasa/plugin.py,sha256=cSmFhSWr5WQyYXdJOWwgH4ra_2kbhoNLZAtnqcsGny4,3071
628
627
  rasa/server.py,sha256=eomGM_3SpBxaF_-VfZbkSO_bMk_vI1XLUZjt32f4gcI,59390
629
628
  rasa/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
630
- rasa/shared/constants.py,sha256=RrlkeBkjZikbU0SDXAB6YnaSLbOrTB0puRBa3B5OS1g,12010
629
+ rasa/shared/constants.py,sha256=lGZKYydyfIKz98ZYyXKM0quCatB4R3mPXZZZ0AIHlfY,12073
631
630
  rasa/shared/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
632
631
  rasa/shared/core/command_payload_reader.py,sha256=puHYsp9xbX0YQm2L1NDBItOFmdzI7AzmfGefgcHiCc0,3871
633
632
  rasa/shared/core/constants.py,sha256=kbaZlfjhJWrRhWhYRBjGCj6TeHF03-wuXcD9FXX1plY,6632
634
633
  rasa/shared/core/conversation.py,sha256=0nUhcbQkPDnO3_Rig7oiinrWmPy5fsVQs_U6Fx1hG5c,1384
635
- rasa/shared/core/domain.py,sha256=KccnBgQmyVnWfoCfMh-kfwt7BHuFRKU64-_Sbh5RI20,81175
634
+ rasa/shared/core/domain.py,sha256=piJu4Kr2exC9ehC3e2oNaxPxXkeIhOYoQJQQOuzMw18,81638
636
635
  rasa/shared/core/events.py,sha256=kTUWSpDepj3kpjjXveYXz3h2XcIQV3Sq8h7MTbx5fMw,86489
637
636
  rasa/shared/core/flows/__init__.py,sha256=Z4pBY0qcEbHeOwgmKsyg2Nz4dX9CF67fFCwj2KXSMpg,180
638
637
  rasa/shared/core/flows/constants.py,sha256=0HN3k-apOb_fi8E2AJtUxMxro8jwFVyXQpil-tHEzbM,340
@@ -660,7 +659,9 @@ rasa/shared/core/flows/utils.py,sha256=jOp063Lkt5ZZ832K6gLnlGU6HjHe5iLDzMLiGvugS
660
659
  rasa/shared/core/flows/validation.py,sha256=4IfTR8LoaJcqP8I7NQXjl0Ysmwc7VO7YzCshpiDEDP0,27410
661
660
  rasa/shared/core/flows/yaml_flows_io.py,sha256=85ln95jpkh7ZqDl1cheFa8Q21gnadLjWrW8ADmQlrUQ,14385
662
661
  rasa/shared/core/generator.py,sha256=UAuBPu5UjUhL9djVK-PvrWZcNhRACOEgnRsTleV7eeY,35686
663
- rasa/shared/core/slot_mappings.py,sha256=0jOIk-iSKI-pJObYdk-Bmf-2SPTYFUuCA4H6SONthRA,25847
662
+ rasa/shared/core/policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
663
+ rasa/shared/core/policies/utils.py,sha256=rWE_-48Ovc__V7wOKCJ-2lTerVRtN3iRHV4ZvuU2b2g,3070
664
+ rasa/shared/core/slot_mappings.py,sha256=t-YAYmZpKTkEfrkZuOkJ1ZPcct29lIZJYmp1SsUgoJA,26410
664
665
  rasa/shared/core/slots.py,sha256=KOGC5dqW7yLIZZrNqoMBrqqEmaJMNbKB_0yW7d__1yM,29211
665
666
  rasa/shared/core/trackers.py,sha256=fgSBpaoVm98dQjFhfJGxaDiQN7Gg94AnT_Rk4z_UEms,45271
666
667
  rasa/shared/core/training_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -781,7 +782,7 @@ rasa/tracing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
781
782
  rasa/tracing/config.py,sha256=32X2rqAiHe0e-Iijb5AivjqDs2j03n8xx5mo07NBMI4,12964
782
783
  rasa/tracing/constants.py,sha256=-3vlfI9v_D8f-KB5tuiqBHhszu2WofFQOyjKBn28gyg,2889
783
784
  rasa/tracing/instrumentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
784
- rasa/tracing/instrumentation/attribute_extractors.py,sha256=kGAGnG5WaqjY5ViM62STY3YhOWEyzRkDnYNmDSZSxMU,29397
785
+ rasa/tracing/instrumentation/attribute_extractors.py,sha256=hkdnqIn8PkD1ykxGbPMv-TPHbhtLgOoMQGmwcvfhi2c,29471
785
786
  rasa/tracing/instrumentation/instrumentation.py,sha256=BPI5OoZFbl90kVJzlKEz-eD8cf-CaX_x1t4V9XBhDKo,53625
786
787
  rasa/tracing/instrumentation/intentless_policy_instrumentation.py,sha256=RgixI0FVIzBz19E3onidUpSEwjkAh8paA5_w07PMzFo,4821
787
788
  rasa/tracing/instrumentation/metrics.py,sha256=DI_qIS6sz5KYU4QDcPKfnHxKLL_Ma3wV6diH4_vg85c,12051
@@ -822,9 +823,9 @@ rasa/utils/train_utils.py,sha256=ClJx-6x3-h3Vt6mskacgkcCUJTMXjFPe3zAcy_DfmaU,212
822
823
  rasa/utils/url_tools.py,sha256=dZ1HGkVdWTJB7zYEdwoDIrEuyX9HE5WsxKKFVsXBLE0,1218
823
824
  rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
824
825
  rasa/validator.py,sha256=tAFzUKVbCPRPx0LjCUKY0zSCaX2hgINuaMfK123FCyc,88716
825
- rasa/version.py,sha256=dDsASMVZIa9S9YXmLCSNna0sr6LxTbufRoJkdesv1lU,117
826
- rasa_pro-3.12.4.dist-info/METADATA,sha256=ei5LDMP92_NCK6EtArdkgE9kIdr6QNq4AUp-TV2qAlM,10642
827
- rasa_pro-3.12.4.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
828
- rasa_pro-3.12.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
829
- rasa_pro-3.12.4.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
830
- rasa_pro-3.12.4.dist-info/RECORD,,
826
+ rasa/version.py,sha256=dCdw26gY8ytDoDFG56GDqpByHMafnjQY_VsX_BOyF6c,123
827
+ rasa_pro-3.12.6.dev1.dist-info/METADATA,sha256=NWxqRDfzBbgnaybvxSrmtRY-IHxYt_vr_Q2cUCbshFU,10543
828
+ rasa_pro-3.12.6.dev1.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
829
+ rasa_pro-3.12.6.dev1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
830
+ rasa_pro-3.12.6.dev1.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
831
+ rasa_pro-3.12.6.dev1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
README.md DELETED
@@ -1,38 +0,0 @@
1
- <h1 align="center">Rasa Pro</h1>
2
-
3
- <div align="center">
4
-
5
- [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=RasaHQ_rasa&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=RasaHQ_rasa)
6
- [![Documentation Status](https://img.shields.io/badge/docs-stable-brightgreen.svg)](https://rasa.com/docs/docs/pro/intro)
7
- ![Python version support](https://img.shields.io/pypi/pyversions/rasa-pro)
8
-
9
- </div>
10
-
11
- <hr />
12
-
13
- 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.
14
-
15
- 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.
16
-
17
- **Key Features:**
18
-
19
- - **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.
20
- - **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.
21
- - **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.
22
- - **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.
23
- - **Built-in Security:** Safeguard sensitive data, control access, and ensure secure deployment, essential for production environments that demand high levels of security and compliance.
24
-
25
- A [free developer license](https://rasa.com/docs/pro/intro/#who-rasa-pro-is-for) is available so you can explore and get to know Rasa Pro. It allows you to take your assistant live in production a limited capacity. A paid license is required for larger-scale production use, but all code is visible and can be customized as needed.
26
-
27
- To get started right now, you can
28
-
29
- `pip install rasa-pro`
30
-
31
- Check out our
32
-
33
- - [Rasa-pro Quickstart](https://rasa.com/docs/learn/quickstart/pro),
34
- - [Conversational AI with Language Models (CALM) conceptual rundown](https://rasa.com/docs/learn/concepts/calm),
35
- - [Rasa Pro / CALM tutorial](https://rasa.com/docs/pro/tutorial), and
36
- - [Rasa pro changelog](https://rasa.com/docs/reference/changelogs/rasa-pro-changelog)
37
-
38
- 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"}