rasa-pro 3.13.0.dev8__py3-none-any.whl → 3.13.0.dev10__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 (99) hide show
  1. rasa/cli/export.py +2 -0
  2. rasa/core/channels/development_inspector.py +1 -1
  3. rasa/core/channels/facebook.py +1 -4
  4. rasa/core/channels/inspector/README.md +3 -3
  5. rasa/core/channels/inspector/dist/assets/{arc-c4b064fc.js → arc-02053cc1.js} +1 -1
  6. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-215b5026.js → blockDiagram-38ab4fdb-008b6289.js} +1 -1
  7. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-2b54a0a3.js → c4Diagram-3d4e48cf-fb2597be.js} +1 -1
  8. rasa/core/channels/inspector/dist/assets/channel-078dada8.js +1 -0
  9. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-daacea5f.js → classDiagram-70f12bd4-7f847e00.js} +1 -1
  10. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-930d4dc2.js → classDiagram-v2-f2320105-ba1d689b.js} +1 -1
  11. rasa/core/channels/inspector/dist/assets/clone-5b4516de.js +1 -0
  12. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-83c206ba.js → createText-2e5e7dd3-dd8e67c4.js} +1 -1
  13. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-b0eb01d0.js → edges-e0da2a9e-10784939.js} +1 -1
  14. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-17586500.js → erDiagram-9861fffd-24947ae6.js} +1 -1
  15. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-be2a1776.js → flowDb-956e92f1-a9ced505.js} +1 -1
  16. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-c2120ebd.js → flowDiagram-66a62f08-afda9c7c.js} +1 -1
  17. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-f9613071.js +1 -0
  18. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-a6ab5c48.js → flowchart-elk-definition-4a651766-6ef530b8.js} +1 -1
  19. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-ef613457.js → ganttDiagram-c361ad54-0c7dd39a.js} +1 -1
  20. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-d59185b3.js → gitGraphDiagram-72cf32ee-b57239d6.js} +1 -1
  21. rasa/core/channels/inspector/dist/assets/{graph-0f155405.js → graph-9ed57cec.js} +1 -1
  22. rasa/core/channels/inspector/dist/assets/{index-3862675e-d5f1d1b7.js → index-3862675e-233090de.js} +1 -1
  23. rasa/core/channels/inspector/dist/assets/{index-47737d3a.js → index-72184470.js} +3 -3
  24. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b07d141f.js → infoDiagram-f8f76790-aa116649.js} +1 -1
  25. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-1936d429.js → journeyDiagram-49397b02-e51877cc.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{layout-dde8d0f3.js → layout-3ca3798c.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{line-0c2c7ee0.js → line-26ee10d3.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/{linear-35dd89a4.js → linear-aedded32.js} +1 -1
  29. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-56192851.js → mindmap-definition-fc14e90a-d8957261.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-fc21ed78.js → pieDiagram-8a3498a8-d771f885.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-25e98518.js → quadrantDiagram-120e2f19-09fdf50c.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-546ff1f5.js → requirementDiagram-deff3bca-9f0af02e.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-02d8b82d.js → sankeyDiagram-04a897e0-84415b37.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3ca5a92e.js → sequenceDiagram-704730f1-8dec4055.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-128ea07c.js → stateDiagram-587899a1-c5431d07.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-95f290af.js → stateDiagram-v2-d93cdb3a-274e77d9.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-4984898a.js → styles-6aaf32cf-e364a1d7.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1bf266ba.js → styles-9a916d00-0dae36f6.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-60521c63.js → styles-c10674c1-c4641675.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-a25b6e12.js → svgDrawCommon-08f97a94-831fe9a1.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-0fc086bf.js → timeline-definition-85554ec2-c3304b3a.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-44ee592e.js → xychartDiagram-e933f94c-da799369.js} +1 -1
  43. rasa/core/channels/inspector/dist/index.html +1 -1
  44. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +1 -1
  45. rasa/core/channels/socketio.py +56 -41
  46. rasa/core/channels/studio_chat.py +311 -8
  47. rasa/core/channels/voice_ready/audiocodes.py +1 -1
  48. rasa/core/channels/voice_stream/audiocodes.py +1 -1
  49. rasa/core/channels/voice_stream/browser_audio.py +1 -1
  50. rasa/core/channels/voice_stream/tts/__init__.py +8 -0
  51. rasa/core/channels/voice_stream/voice_channel.py +6 -1
  52. rasa/core/exporter.py +36 -0
  53. rasa/core/information_retrieval/faiss.py +18 -11
  54. rasa/core/information_retrieval/ingestion/__init__.py +0 -0
  55. rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
  56. rasa/core/nlg/contextual_response_rephraser.py +10 -1
  57. rasa/core/policies/enterprise_search_policy.py +151 -258
  58. rasa/core/policies/enterprise_search_policy_config.py +242 -0
  59. rasa/core/policies/intentless_policy.py +47 -10
  60. rasa/dialogue_understanding/coexistence/llm_based_router.py +9 -6
  61. rasa/dialogue_understanding/commands/cancel_flow_command.py +3 -1
  62. rasa/dialogue_understanding/commands/correct_slots_command.py +1 -3
  63. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
  64. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +78 -0
  65. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +2 -2
  66. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +2 -2
  67. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +8 -11
  68. rasa/dialogue_understanding/patterns/cancel.py +1 -2
  69. rasa/dialogue_understanding/patterns/clarify.py +1 -1
  70. rasa/dialogue_understanding/patterns/correction.py +2 -2
  71. rasa/dialogue_understanding/processor/command_processor.py +3 -4
  72. rasa/dialogue_understanding/stack/utils.py +3 -1
  73. rasa/engine/graph.py +2 -2
  74. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +1 -5
  75. rasa/shared/constants.py +11 -0
  76. rasa/shared/core/command_payload_reader.py +1 -5
  77. rasa/shared/core/events.py +1 -3
  78. rasa/shared/core/flows/validation.py +25 -5
  79. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
  80. rasa/shared/providers/_configs/azure_openai_client_config.py +2 -2
  81. rasa/shared/providers/_configs/default_litellm_client_config.py +1 -1
  82. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -1
  83. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  84. rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -1
  85. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -1
  86. rasa/shared/providers/_configs/utils.py +0 -99
  87. rasa/shared/utils/common.py +1 -1
  88. rasa/shared/utils/configs.py +110 -0
  89. rasa/shared/utils/llm.py +30 -0
  90. rasa/tracing/instrumentation/attribute_extractors.py +10 -5
  91. rasa/version.py +1 -1
  92. {rasa_pro-3.13.0.dev8.dist-info → rasa_pro-3.13.0.dev10.dist-info}/METADATA +3 -3
  93. {rasa_pro-3.13.0.dev8.dist-info → rasa_pro-3.13.0.dev10.dist-info}/RECORD +96 -91
  94. rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +0 -1
  95. rasa/core/channels/inspector/dist/assets/clone-e847561e.js +0 -1
  96. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +0 -1
  97. {rasa_pro-3.13.0.dev8.dist-info → rasa_pro-3.13.0.dev10.dist-info}/NOTICE +0 -0
  98. {rasa_pro-3.13.0.dev8.dist-info → rasa_pro-3.13.0.dev10.dist-info}/WHEEL +0 -0
  99. {rasa_pro-3.13.0.dev8.dist-info → rasa_pro-3.13.0.dev10.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,242 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import asdict, dataclass
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import structlog
7
+
8
+ from rasa.core.constants import (
9
+ POLICY_MAX_HISTORY,
10
+ POLICY_PRIORITY,
11
+ SEARCH_POLICY_PRIORITY,
12
+ )
13
+ from rasa.shared.constants import (
14
+ EMBEDDINGS_CONFIG_KEY,
15
+ LLM_CONFIG_KEY,
16
+ MAX_COMPLETION_TOKENS_CONFIG_KEY,
17
+ MAX_RETRIES_CONFIG_KEY,
18
+ MODEL_CONFIG_KEY,
19
+ OPENAI_PROVIDER,
20
+ PROMPT_CONFIG_KEY,
21
+ PROMPT_TEMPLATE_CONFIG_KEY,
22
+ PROVIDER_CONFIG_KEY,
23
+ TEMPERATURE_CONFIG_KEY,
24
+ TIMEOUT_CONFIG_KEY,
25
+ )
26
+ from rasa.shared.utils.configs import (
27
+ raise_deprecation_warnings,
28
+ resolve_aliases,
29
+ validate_forbidden_keys,
30
+ validate_required_keys,
31
+ )
32
+ from rasa.shared.utils.llm import (
33
+ DEFAULT_OPENAI_CHAT_MODEL_NAME,
34
+ DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
35
+ resolve_model_client_config,
36
+ )
37
+
38
+ structlogger = structlog.get_logger()
39
+
40
+
41
+ SOURCE_PROPERTY = "source"
42
+ VECTOR_STORE_TYPE_PROPERTY = "type"
43
+ VECTOR_STORE_PROPERTY = "vector_store"
44
+ VECTOR_STORE_THRESHOLD_PROPERTY = "threshold"
45
+ TRACE_TOKENS_PROPERTY = "trace_prompt_tokens"
46
+ CITATION_ENABLED_PROPERTY = "citation_enabled"
47
+ USE_LLM_PROPERTY = "use_generative_llm"
48
+ CHECK_RELEVANCY_PROPERTY = "check_relevancy"
49
+ MAX_MESSAGES_IN_QUERY_KEY = "max_messages_in_query"
50
+
51
+ DEFAULT_VECTOR_STORE_TYPE = "faiss"
52
+ DEFAULT_VECTOR_STORE_THRESHOLD = 0.0
53
+ DEFAULT_VECTOR_STORE = {
54
+ VECTOR_STORE_TYPE_PROPERTY: DEFAULT_VECTOR_STORE_TYPE,
55
+ SOURCE_PROPERTY: "./docs",
56
+ VECTOR_STORE_THRESHOLD_PROPERTY: DEFAULT_VECTOR_STORE_THRESHOLD,
57
+ }
58
+
59
+ DEFAULT_CHECK_RELEVANCY_PROPERTY = False
60
+ DEFAULT_USE_LLM_PROPERTY = True
61
+ DEFAULT_CITATION_ENABLED_PROPERTY = False
62
+ DEFAULT_TRACE_PROMPT_TOKEN_PROPERTY = False
63
+
64
+ DEFAULT_MAX_MESSAGES_IN_QUERY = 2
65
+
66
+ DEFAULT_LLM_CONFIG = {
67
+ PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
68
+ MODEL_CONFIG_KEY: DEFAULT_OPENAI_CHAT_MODEL_NAME,
69
+ TIMEOUT_CONFIG_KEY: 10,
70
+ TEMPERATURE_CONFIG_KEY: 0.0,
71
+ MAX_COMPLETION_TOKENS_CONFIG_KEY: 256,
72
+ MAX_RETRIES_CONFIG_KEY: 1,
73
+ }
74
+
75
+ DEFAULT_EMBEDDINGS_CONFIG = {
76
+ PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
77
+ MODEL_CONFIG_KEY: DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
78
+ }
79
+
80
+ DEFAULT_ENTERPRISE_SEARCH_CONFIG = {
81
+ POLICY_PRIORITY: SEARCH_POLICY_PRIORITY,
82
+ VECTOR_STORE_PROPERTY: DEFAULT_VECTOR_STORE,
83
+ }
84
+
85
+ REQUIRED_KEYS: List[str] = []
86
+
87
+ FORBIDDEN_KEYS: List[str] = []
88
+
89
+ DEPRECATED_ALIASES_TO_STANDARD_KEY_MAPPING = {
90
+ PROMPT_CONFIG_KEY: PROMPT_TEMPLATE_CONFIG_KEY
91
+ }
92
+
93
+
94
+ @dataclass
95
+ class EnterpriseSearchPolicyConfig:
96
+ """Parses configuration for Enterprise Search Policy."""
97
+
98
+ # TODO: llm_config, embeddings_config, and vector_store_config should also be parsed
99
+ # as "Config" objects. Likely part of a broader Rasa 4.0 rewrite where all
100
+ # components rely on configuration parser. So, for example, llm_config and
101
+ # embeddings_config should be parsed as ClientConfig objects, and
102
+ # vector_store_config parsed as VectorStoreConfig object.
103
+ llm_config: dict
104
+ embeddings_config: dict
105
+ vector_store_config: dict
106
+
107
+ prompt_template: str
108
+
109
+ use_generative_llm: bool = DEFAULT_USE_LLM_PROPERTY
110
+ enable_citation: bool = DEFAULT_CITATION_ENABLED_PROPERTY
111
+ check_relevancy: bool = DEFAULT_CHECK_RELEVANCY_PROPERTY
112
+
113
+ max_history: Optional[int] = None
114
+ max_messages_in_query: int = DEFAULT_MAX_MESSAGES_IN_QUERY
115
+ trace_prompt_tokens: bool = DEFAULT_TRACE_PROMPT_TOKEN_PROPERTY
116
+
117
+ @property
118
+ def vector_store_type(self) -> str:
119
+ # TODO: In the future this should ideally be part of the Vector config
120
+ # and not the property of the EnterpriseSearch config
121
+ return (
122
+ self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY)
123
+ or DEFAULT_VECTOR_STORE_TYPE
124
+ )
125
+
126
+ @property
127
+ def vector_store_threshold(self) -> float:
128
+ # TODO: In the future this should ideally be part of the Vector config
129
+ # and not the property of the EnterpriseSearch config
130
+ return (
131
+ self.vector_store_config.get(VECTOR_STORE_THRESHOLD_PROPERTY)
132
+ or DEFAULT_VECTOR_STORE_THRESHOLD
133
+ )
134
+
135
+ @property
136
+ def vector_store_source(self) -> Optional[str]:
137
+ # TODO: In the future this should ideally be part of the Vector config
138
+ # and not the property of the EnterpriseSearch config
139
+ return self.vector_store_config.get(SOURCE_PROPERTY)
140
+
141
+ def __post_init__(self) -> None:
142
+ if self.check_relevancy and not self.use_generative_llm:
143
+ structlogger.warning(
144
+ "enterprise_search_policy"
145
+ ".relevancy_check_enabled_with_disabled_generative_search",
146
+ event_info=(
147
+ f"The config parameter '{CHECK_RELEVANCY_PROPERTY}' is set to"
148
+ f"'True', but the generative search is disabled (config"
149
+ f"parameter '{USE_LLM_PROPERTY}' is set to 'False'). As a result, "
150
+ "the relevancy check for the generative search will be disabled. "
151
+ f"To use this check, set the config parameter '{USE_LLM_PROPERTY}' "
152
+ f"to `True`."
153
+ ),
154
+ )
155
+ if self.enable_citation and not self.use_generative_llm:
156
+ structlogger.warning(
157
+ "enterprise_search_policy"
158
+ ".citation_enabled_with_disabled_generative_search",
159
+ event_info=(
160
+ f"The config parameter '{CITATION_ENABLED_PROPERTY}' is set to"
161
+ f"'True', but the generative search is disabled (config"
162
+ f"parameter '{USE_LLM_PROPERTY}' is set to 'False'). As a result, "
163
+ "the citation for the generative search will be disabled. "
164
+ f"To use this check, set the config parameter '{USE_LLM_PROPERTY}' "
165
+ f"to `True`."
166
+ ),
167
+ )
168
+
169
+ @classmethod
170
+ def from_dict(cls, config: dict) -> EnterpriseSearchPolicyConfig:
171
+ """
172
+ Initializes a dataclass from the passed config.
173
+
174
+ Args:
175
+ config: (dict) The config from which to initialize.
176
+
177
+ Raises:
178
+ ValueError: Config is missing required keys.
179
+
180
+ Returns:
181
+ AzureOpenAIClientConfig
182
+ """
183
+ # Resolve LLM config
184
+ llm_config = (
185
+ resolve_model_client_config(
186
+ config.get(LLM_CONFIG_KEY), EnterpriseSearchPolicyConfig.__name__
187
+ )
188
+ or DEFAULT_LLM_CONFIG
189
+ )
190
+
191
+ # Resolve embeddings config
192
+ embeddings_config = (
193
+ resolve_model_client_config(
194
+ config.get(EMBEDDINGS_CONFIG_KEY), EnterpriseSearchPolicyConfig.__name__
195
+ )
196
+ or DEFAULT_EMBEDDINGS_CONFIG
197
+ )
198
+
199
+ # Vector store config
200
+ vector_store_config = config.get(VECTOR_STORE_PROPERTY, DEFAULT_VECTOR_STORE)
201
+
202
+ # Check for deprecated keys
203
+ raise_deprecation_warnings(
204
+ config, DEPRECATED_ALIASES_TO_STANDARD_KEY_MAPPING, "EnterpriseSearchPolicy"
205
+ )
206
+ # Resolve any potential aliases (e.g. 'prompt_template' vs 'prompt')
207
+ config = cls.resolve_config_aliases(config)
208
+
209
+ # Validate that the required keys are present
210
+ validate_required_keys(config, REQUIRED_KEYS)
211
+ # Validate that the forbidden keys are not present
212
+ validate_forbidden_keys(config, FORBIDDEN_KEYS)
213
+
214
+ this = EnterpriseSearchPolicyConfig(
215
+ llm_config=llm_config,
216
+ embeddings_config=embeddings_config,
217
+ vector_store_config=vector_store_config,
218
+ prompt_template=config.get(PROMPT_TEMPLATE_CONFIG_KEY),
219
+ use_generative_llm=config.get(USE_LLM_PROPERTY, DEFAULT_USE_LLM_PROPERTY),
220
+ enable_citation=config.get(
221
+ CITATION_ENABLED_PROPERTY, DEFAULT_CITATION_ENABLED_PROPERTY
222
+ ),
223
+ check_relevancy=config.get(
224
+ CHECK_RELEVANCY_PROPERTY, DEFAULT_CHECK_RELEVANCY_PROPERTY
225
+ ),
226
+ max_history=config.get(POLICY_MAX_HISTORY),
227
+ max_messages_in_query=config.get(
228
+ MAX_MESSAGES_IN_QUERY_KEY, DEFAULT_MAX_MESSAGES_IN_QUERY
229
+ ),
230
+ trace_prompt_tokens=config.get(
231
+ TRACE_TOKENS_PROPERTY, DEFAULT_TRACE_PROMPT_TOKEN_PROPERTY
232
+ ),
233
+ )
234
+ return this
235
+
236
+ def to_dict(self) -> dict:
237
+ """Converts the config instance into a dictionary."""
238
+ return asdict(self)
239
+
240
+ @staticmethod
241
+ def resolve_config_aliases(config: Dict[str, Any]) -> Dict[str, Any]:
242
+ return resolve_aliases(config, DEPRECATED_ALIASES_TO_STANDARD_KEY_MAPPING)
@@ -38,6 +38,7 @@ from rasa.shared.constants import (
38
38
  MODEL_NAME_CONFIG_KEY,
39
39
  OPENAI_PROVIDER,
40
40
  PROMPT_CONFIG_KEY,
41
+ PROMPT_TEMPLATE_CONFIG_KEY,
41
42
  PROVIDER_CONFIG_KEY,
42
43
  TEMPERATURE_CONFIG_KEY,
43
44
  TIMEOUT_CONFIG_KEY,
@@ -56,7 +57,10 @@ from rasa.shared.providers.embedding._langchain_embedding_client_adapter import
56
57
  _LangchainEmbeddingClientAdapter,
57
58
  )
58
59
  from rasa.shared.providers.llm.llm_client import LLMClient
59
- from rasa.shared.utils.constants import LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
60
+ from rasa.shared.utils.constants import (
61
+ LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
62
+ LOG_COMPONENT_SOURCE_METHOD_INIT,
63
+ )
60
64
  from rasa.shared.utils.health_check.embeddings_health_check_mixin import (
61
65
  EmbeddingsHealthCheckMixin,
62
66
  )
@@ -68,6 +72,7 @@ from rasa.shared.utils.llm import (
68
72
  DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
69
73
  DEFAULT_OPENAI_MAX_GENERATED_TOKENS,
70
74
  USER,
75
+ check_prompt_config_keys_and_warn_if_deprecated,
71
76
  combine_custom_and_default_config,
72
77
  embedder_factory,
73
78
  get_prompt_template,
@@ -119,9 +124,12 @@ DEFAULT_EMBEDDINGS_CONFIG = {
119
124
  MODEL_CONFIG_KEY: DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
120
125
  }
121
126
 
122
- DEFAULT_INTENTLESS_PROMPT_TEMPLATE = importlib.resources.open_text(
127
+ DEFAULT_INTENTLESS_PROMPT_TEMPLATE_FILE_NAME = importlib.resources.open_text(
123
128
  "rasa.core.policies", "intentless_prompt_template.jinja2"
124
129
  ).name
130
+ DEFAULT_INTENTLESS_PROMPT_TEMPLATE = importlib.resources.read_text(
131
+ "rasa.core.policies", "intentless_prompt_template.jinja2"
132
+ )
125
133
 
126
134
  INTENTLESS_PROMPT_TEMPLATE_FILE_NAME = "intentless_policy_prompt.jinja2"
127
135
  INTENTLESS_CONFIG_FILE_NAME = "config.json"
@@ -345,7 +353,7 @@ class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
345
353
  # ensures that the policy will not override a deterministic policy
346
354
  # which utilizes the nlu predictions confidence (e.g. Memoization).
347
355
  NLU_ABSTENTION_THRESHOLD: 0.9,
348
- PROMPT_CONFIG_KEY: DEFAULT_INTENTLESS_PROMPT_TEMPLATE,
356
+ PROMPT_TEMPLATE_CONFIG_KEY: None, # TODO: remove in Rasa 4.0.0
349
357
  }
350
358
 
351
359
  @staticmethod
@@ -402,11 +410,43 @@ class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
402
410
  self.response_index = responses_docsearch
403
411
  self.conversation_samples_index = samples_docsearch
404
412
  self.embedder = self._create_plain_embedder(config)
405
- self.prompt_template = prompt_template or rasa.shared.utils.io.read_file(
406
- self.config[PROMPT_CONFIG_KEY]
413
+
414
+ # Warn if the prompt config key is used to set the prompt template
415
+ check_prompt_config_keys_and_warn_if_deprecated(config, "intentless_policy")
416
+
417
+ self.prompt_template = prompt_template or self._resolve_prompt_template(
418
+ config, LOG_COMPONENT_SOURCE_METHOD_INIT
407
419
  )
408
420
  self.trace_prompt_tokens = self.config.get("trace_prompt_tokens", False)
409
421
 
422
+ @classmethod
423
+ def _resolve_prompt_template(
424
+ cls: Any,
425
+ config: dict,
426
+ log_source_method: str,
427
+ ) -> str:
428
+ """Resolves the prompt template from the config.
429
+
430
+ Args:
431
+ config: The config to resolve the prompt template from.
432
+ log_source_method: The method from which the prompt template is resolved.
433
+
434
+ Returns:
435
+ The resolved prompt template.
436
+ """
437
+ # Prefer prompt template over prompt config key.
438
+ prompt_template_file = (
439
+ config.get(PROMPT_TEMPLATE_CONFIG_KEY)
440
+ or config.get(PROMPT_CONFIG_KEY)
441
+ or DEFAULT_INTENTLESS_PROMPT_TEMPLATE_FILE_NAME
442
+ )
443
+ return get_prompt_template(
444
+ prompt_template_file,
445
+ DEFAULT_INTENTLESS_PROMPT_TEMPLATE,
446
+ log_source_component=IntentlessPolicy.__name__,
447
+ log_source_method=log_source_method,
448
+ )
449
+
410
450
  @classmethod
411
451
  def _create_plain_embedder(cls, config: Dict[Text, Any]) -> Embeddings:
412
452
  """Creates an embedder that uses the OpenAI API.
@@ -945,11 +985,8 @@ class IntentlessPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Policy):
945
985
  @classmethod
946
986
  def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
947
987
  """Add a fingerprint of intentless policy for the graph."""
948
- prompt_template = get_prompt_template(
949
- config.get(PROMPT_CONFIG_KEY),
950
- DEFAULT_INTENTLESS_PROMPT_TEMPLATE,
951
- log_source_component=IntentlessPolicy.__name__,
952
- log_source_method=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
988
+ prompt_template = cls._resolve_prompt_template(
989
+ config, LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
953
990
  )
954
991
 
955
992
  llm_config = resolve_model_client_config(
@@ -15,9 +15,7 @@ from rasa.dialogue_understanding.coexistence.constants import (
15
15
  )
16
16
  from rasa.dialogue_understanding.commands import Command, SetSlotCommand
17
17
  from rasa.dialogue_understanding.commands.noop_command import NoopCommand
18
- from rasa.dialogue_understanding.generator.constants import (
19
- LLM_CONFIG_KEY,
20
- )
18
+ from rasa.dialogue_understanding.generator.constants import LLM_CONFIG_KEY
21
19
  from rasa.engine.graph import ExecutionContext, GraphComponent
22
20
  from rasa.engine.recipes.default_recipe import DefaultV1Recipe
23
21
  from rasa.engine.storage.resource import Resource
@@ -28,6 +26,7 @@ from rasa.shared.constants import (
28
26
  MODEL_CONFIG_KEY,
29
27
  OPENAI_PROVIDER,
30
28
  PROMPT_CONFIG_KEY,
29
+ PROMPT_TEMPLATE_CONFIG_KEY,
31
30
  PROVIDER_CONFIG_KEY,
32
31
  ROUTE_TO_CALM_SLOT,
33
32
  TEMPERATURE_CONFIG_KEY,
@@ -46,6 +45,7 @@ from rasa.shared.utils.health_check.llm_health_check_mixin import LLMHealthCheck
46
45
  from rasa.shared.utils.io import deep_container_fingerprint
47
46
  from rasa.shared.utils.llm import (
48
47
  DEFAULT_OPENAI_CHAT_MODEL_NAME,
48
+ check_prompt_config_keys_and_warn_if_deprecated,
49
49
  get_prompt_template,
50
50
  llm_factory,
51
51
  resolve_model_client_config,
@@ -90,7 +90,7 @@ class LLMBasedRouter(LLMHealthCheckMixin, GraphComponent):
90
90
  def get_default_config() -> Dict[str, Any]:
91
91
  """The component's default config (see parent class for full docstring)."""
92
92
  return {
93
- PROMPT_CONFIG_KEY: None,
93
+ PROMPT_TEMPLATE_CONFIG_KEY: None, # TODO: remove in Rasa 4.0.0
94
94
  CALM_ENTRY: {STICKY: None},
95
95
  NLU_ENTRY: {
96
96
  NON_STICKY: "handles chitchat",
@@ -111,10 +111,13 @@ class LLMBasedRouter(LLMHealthCheckMixin, GraphComponent):
111
111
  self.config.get(LLM_CONFIG_KEY), LLMBasedRouter.__name__
112
112
  )
113
113
 
114
+ # Warn if the prompt config key is used to set the prompt template
115
+ check_prompt_config_keys_and_warn_if_deprecated(config, "llm_based_router")
116
+
114
117
  self.prompt_template = (
115
118
  prompt_template
116
119
  or get_prompt_template(
117
- config.get(PROMPT_CONFIG_KEY),
120
+ config.get(PROMPT_TEMPLATE_CONFIG_KEY) or config.get(PROMPT_CONFIG_KEY),
118
121
  DEFAULT_COMMAND_PROMPT_TEMPLATE,
119
122
  log_source_component=LLMBasedRouter.__name__,
120
123
  log_source_method=LOG_COMPONENT_SOURCE_METHOD_INIT,
@@ -327,7 +330,7 @@ class LLMBasedRouter(LLMHealthCheckMixin, GraphComponent):
327
330
  def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
328
331
  """Add a fingerprint of llm based router for the graph."""
329
332
  prompt_template = get_prompt_template(
330
- config.get(PROMPT_CONFIG_KEY),
333
+ config.get(PROMPT_TEMPLATE_CONFIG_KEY) or config.get(PROMPT_CONFIG_KEY),
331
334
  DEFAULT_COMMAND_PROMPT_TEMPLATE,
332
335
  log_source_component=LLMBasedRouter.__name__,
333
336
  log_source_method=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
@@ -95,7 +95,9 @@ class CancelFlowCommand(Command):
95
95
  original_stack = original_tracker.stack
96
96
 
97
97
  applied_events: List[Event] = []
98
- user_frame = top_user_flow_frame(original_stack)
98
+ user_frame = top_user_flow_frame(
99
+ original_stack, ignore_call_and_link_frames=False
100
+ )
99
101
  current_flow = user_frame.flow(all_flows) if user_frame else None
100
102
 
101
103
  if not current_flow:
@@ -274,9 +274,7 @@ class CorrectSlotsCommand(Command):
274
274
  # we shouldn't end up here as a correction shouldn't be triggered
275
275
  # if we are not in any flow. but just in case we do, we
276
276
  # just skip the command.
277
- structlogger.warning(
278
- "command_executor.correct_slots.no_active_flow", command=self
279
- )
277
+ structlogger.warning("command_executor.correct_slots.no_active_flow")
280
278
  return []
281
279
 
282
280
  structlogger.debug("command_executor.correct_slots", command=self)
@@ -190,9 +190,9 @@ class NLUCommandAdapter(GraphComponent, CommandGenerator):
190
190
  if len(commands) > 1:
191
191
  structlogger.warning(
192
192
  "nlu_command_adapter.predict_commands",
193
- messag=f"Two many flows found that are triggered by the "
193
+ message=f"Too many flows found that are triggered by the "
194
194
  f"intent '{message.get(INTENT)['name']}'. Take the first one.",
195
- commands=commands,
195
+ commands=[command.__class__.__name__ for command in commands],
196
196
  )
197
197
  commands = [commands[0]]
198
198
 
@@ -0,0 +1,78 @@
1
+ ## Task Description
2
+ Your task is to analyze the current conversation context and generate a list of actions to start new business processes that we call flows, to extract slots, or respond to off-topic and knowledge requests.
3
+
4
+ ---
5
+
6
+ ## Available Actions:
7
+ * `start flow flow_name`: Start a flow. For example, `start flow transfer_money` or `start flow list_contacts`.
8
+ * `set slot slot_name slot_value`: Set a slot for the active flow. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
9
+ * `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: When a message could refer to multiple flows, list the possible flows as options to clarify. Example: `disambiguate flows list_contacts add_contact remove_contact`.
10
+ * `search and reply`: Provide a response from the knowledge base to address the user's inquiry when no flows fit, including domain knowledge, FAQs, and all off-topic or social messages.
11
+ * `cancel flow`: Cancel the current flow if the user requests it.
12
+
13
+ ---
14
+
15
+ ## General Instructions
16
+ ### Start Flow
17
+ * Only start a flow if the user's message is clear and fully addressed by that flow's description and purpose.
18
+ * Pay close attention to exact wording and scope in the flow description — do not assume or “stretch” the intended use of a flow.
19
+ ### Set Slot
20
+ * Do not fill slots with abstract values or placeholders.
21
+ * For categorical slots, try to match the user message with allowed slot values. Use "other" if you cannot match it.
22
+ * Set the boolean slots based on the user's response. Map positive responses to `True`, and negative to `False`.
23
+ * Extract text slot values exactly as provided by the user. Avoid assumptions, format changes, or partial extractions.
24
+ ### Disambiguate Flows
25
+ * Use `disambiguate flows` when the user's message matches multiple flows and you cannot decide which flow is most appropriate.
26
+ * If the user message is short and not precise enough to start a flow or `search and reply`, disambiguate.
27
+ * If a single flow is a strong/plausible fit, prefer starting that flow directly.
28
+ * If a user's message unambiguously and distinctly matches multiple flows, start all relevant flows at once (rather than disambiguating).
29
+ ### Search and Reply
30
+ * Only start `search and reply` if the user intent is clear.
31
+ * Flow Priority: If you are unsure between starting a flow or `search and reply`, always prioritize starting a flow.
32
+ ### Cancel Flow
33
+ * Do not cancel any flow unless the user explicitly requests it.
34
+ * Multiple flows can be started without cancelling the previous, if the user wants to pursue multiple processes.
35
+ ### General Tips
36
+ * Only use information provided by the user.
37
+ * Strictly adhere to the provided action format.
38
+ * Focus on the last message and take it one step at a time.
39
+ * Use the previous conversation steps only to aid understanding.
40
+
41
+ ---
42
+
43
+ ## Decision Rule Table
44
+ | Condition | Action |
45
+ |-------------------------------------------------------|--------------------|
46
+ | Flow perfectly matches user's message | start flow |
47
+ | Multiple flows are equally strong, relevant matches | disambiguate flows |
48
+ | User's message is unclear or imprecise | disambiguate flows |
49
+ | No flow fits at all, but knowledge base may help | search and reply |
50
+
51
+ ---
52
+
53
+ ## Available Flows and Slots
54
+ Use the following structured data:
55
+ ```json
56
+ {"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 %}]}
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Current State
62
+ {% if current_flow != None %}Use the following structured data:
63
+ ```json
64
+ {"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 %}]}
65
+ ```{% else %}
66
+ You are currently not inside any flow.{% endif %}
67
+
68
+ ---
69
+
70
+ ## Conversation History
71
+ {{ current_conversation }}
72
+
73
+ ---
74
+
75
+ ## Task
76
+ Create an action list with one action per line in response to the user's last message: """{{ user_message }}""".
77
+
78
+ Your action list:
@@ -59,10 +59,10 @@ MODEL_PROMPT_MAPPER = {
59
59
  ),
60
60
  f"{AWS_BEDROCK_PROVIDER}/anthropic."
61
61
  f"{MODEL_NAME_CLAUDE_3_5_SONNET_20240620}-v1:0": (
62
- "command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2"
62
+ "command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2"
63
63
  ),
64
64
  f"{ANTHROPIC_PROVIDER}/{MODEL_NAME_CLAUDE_3_5_SONNET_20240620}": (
65
- "command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2"
65
+ "command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2"
66
66
  ),
67
67
  }
68
68
 
@@ -113,7 +113,7 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
113
113
  def get_default_config() -> Dict[str, Any]:
114
114
  """The component's default config (see parent class for full docstring)."""
115
115
  return {
116
- PROMPT_TEMPLATE_CONFIG_KEY: None,
116
+ PROMPT_TEMPLATE_CONFIG_KEY: None, # TODO: remove in Rasa 4.0.0
117
117
  USER_INPUT_CONFIG_KEY: None,
118
118
  LLM_CONFIG_KEY: None,
119
119
  FLOW_RETRIEVAL_KEY: FlowRetrieval.get_default_config(),
@@ -212,7 +212,7 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
212
212
  event_info=(
213
213
  "ProviderClientAPIException occurred while predicting commands."
214
214
  ),
215
- commands=commands,
215
+ commands=commands, # no PII
216
216
  )
217
217
 
218
218
  if not commands and not prior_commands:
@@ -16,7 +16,10 @@ from rasa.shared.constants import (
16
16
  PROMPT_CONFIG_KEY,
17
17
  PROMPT_TEMPLATE_CONFIG_KEY,
18
18
  )
19
- from rasa.shared.utils.llm import get_prompt_template
19
+ from rasa.shared.utils.llm import (
20
+ check_prompt_config_keys_and_warn_if_deprecated,
21
+ get_prompt_template,
22
+ )
20
23
 
21
24
  DEFAULT_COMMAND_PROMPT_TEMPLATE = importlib.resources.read_text(
22
25
  "rasa.dialogue_understanding.generator.prompt_templates",
@@ -52,16 +55,10 @@ class SingleStepLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
52
55
  **kwargs,
53
56
  )
54
57
 
55
- # Set the prompt template
56
- if config.get(PROMPT_CONFIG_KEY):
57
- structlogger.warning(
58
- "single_step_llm_command_generator.init",
59
- event_info=(
60
- "The config parameter 'prompt' is deprecated "
61
- "and will be removed in Rasa 4.0.0. "
62
- "Please use the config parameter 'prompt_template' instead. "
63
- ),
64
- )
58
+ # Warn if the prompt config key is used to set the prompt template
59
+ check_prompt_config_keys_and_warn_if_deprecated(
60
+ config, "single_step_llm_command_generator"
61
+ )
65
62
 
66
63
  @staticmethod
67
64
  def get_component_command_syntax_version() -> CommandSyntaxVersion:
@@ -90,7 +90,7 @@ class ActionCancelFlow(action.Action):
90
90
  return []
91
91
 
92
92
  if not isinstance(top, CancelPatternFlowStackFrame):
93
- structlogger.warning("action.cancel_flow.no_cancel_frame", top=top)
93
+ structlogger.warning("action.cancel_flow.no_cancel_frame")
94
94
  return []
95
95
 
96
96
  for canceled_frame_id in top.canceled_frames:
@@ -105,7 +105,6 @@ class ActionCancelFlow(action.Action):
105
105
  else:
106
106
  structlogger.warning(
107
107
  "action.cancel_flow.frame_not_found",
108
- dialogue_stack=stack,
109
108
  frame_id=canceled_frame_id,
110
109
  )
111
110
 
@@ -89,7 +89,7 @@ class ActionClarifyFlows(action.Action):
89
89
  return []
90
90
 
91
91
  if not isinstance(top, ClarifyPatternFlowStackFrame):
92
- structlogger.warning("action.clarify_flows.no_clarification_frame", top=top)
92
+ structlogger.warning("action.clarify_flows.no_clarification_frame")
93
93
  return []
94
94
 
95
95
  options_string = self.assemble_options_string(top.names)
@@ -114,7 +114,8 @@ class ActionCorrectFlowSlot(action.Action):
114
114
 
115
115
  if not isinstance(top, CorrectionPatternFlowStackFrame):
116
116
  structlogger.warning(
117
- "action.correct_flow_slot.no_correction_frame", top=top
117
+ "action.correct_flow_slot.no_correction_frame",
118
+ top=top, # no PII
118
119
  )
119
120
  return []
120
121
 
@@ -246,7 +247,6 @@ def reset_stack_on_tracker_to_prior_state(
246
247
  "action.correct_flow_slot.no_target_frame_found",
247
248
  reset_step_id=reset_step_id,
248
249
  reset_flow_id=reset_flow_id,
249
- stack_to_reset_to=stack_to_reset_to,
250
250
  )
251
251
  return tracker.stack
252
252
 
@@ -348,7 +348,6 @@ def get_current_collect_step(
348
348
  # but no flow that triggered it. this should never happen.
349
349
  structlogger.warning(
350
350
  "command_processor.get_current_collect_step.no_flow_on_stack",
351
- stack=dialogue_stack,
352
351
  )
353
352
  return None
354
353
 
@@ -358,7 +357,7 @@ def get_current_collect_step(
358
357
  # step from it
359
358
  structlogger.warning(
360
359
  "command_processor.get_current_collect_step.no_step_for_frame",
361
- frame=frame_that_triggered_collect_infos,
360
+ frame=frame_that_triggered_collect_infos.frame_id,
362
361
  )
363
362
  return None
364
363
 
@@ -724,7 +723,7 @@ def clean_up_chitchat_command(
724
723
  )
725
724
  structlogger.warn(
726
725
  "command_processor.clean_up_chitchat_command.pattern_chitchat_not_found",
727
- command=resulting_commands[0],
726
+ command=resulting_commands[0], # no PII
728
727
  )
729
728
  return resulting_commands
730
729
 
@@ -742,7 +741,7 @@ def clean_up_chitchat_command(
742
741
  )
743
742
  structlogger.warn(
744
743
  "command_processor.clean_up_chitchat_command.replace_chitchat_answer_with_cannot_handle",
745
- command=resulting_commands[0],
744
+ command=resulting_commands[0], # no PII
746
745
  pattern_chitchat_uses_action_trigger_chitchat=has_action_trigger_chitchat,
747
746
  defined_intentless_policy_in_config=defines_intentless_policy,
748
747
  )