rasa-pro 3.10.15__py3-none-any.whl → 3.11.0__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 (238) hide show
  1. rasa/__main__.py +31 -15
  2. rasa/api.py +12 -2
  3. rasa/cli/arguments/default_arguments.py +24 -4
  4. rasa/cli/arguments/run.py +15 -0
  5. rasa/cli/arguments/shell.py +5 -1
  6. rasa/cli/arguments/train.py +17 -9
  7. rasa/cli/evaluate.py +7 -7
  8. rasa/cli/inspect.py +19 -7
  9. rasa/cli/interactive.py +1 -0
  10. rasa/cli/project_templates/calm/config.yml +5 -7
  11. rasa/cli/project_templates/calm/endpoints.yml +15 -2
  12. rasa/cli/project_templates/tutorial/config.yml +8 -5
  13. rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
  14. rasa/cli/project_templates/tutorial/data/patterns.yml +5 -0
  15. rasa/cli/project_templates/tutorial/domain.yml +14 -0
  16. rasa/cli/project_templates/tutorial/endpoints.yml +5 -0
  17. rasa/cli/run.py +7 -0
  18. rasa/cli/scaffold.py +4 -2
  19. rasa/cli/studio/upload.py +0 -15
  20. rasa/cli/train.py +14 -53
  21. rasa/cli/utils.py +14 -11
  22. rasa/cli/x.py +7 -7
  23. rasa/constants.py +3 -1
  24. rasa/core/actions/action.py +77 -33
  25. rasa/core/actions/action_hangup.py +29 -0
  26. rasa/core/actions/action_repeat_bot_messages.py +89 -0
  27. rasa/core/actions/e2e_stub_custom_action_executor.py +5 -1
  28. rasa/core/actions/http_custom_action_executor.py +4 -0
  29. rasa/core/agent.py +2 -2
  30. rasa/core/brokers/kafka.py +3 -1
  31. rasa/core/brokers/pika.py +3 -1
  32. rasa/core/channels/__init__.py +10 -6
  33. rasa/core/channels/channel.py +41 -4
  34. rasa/core/channels/development_inspector.py +150 -46
  35. rasa/core/channels/inspector/README.md +1 -1
  36. rasa/core/channels/inspector/dist/assets/{arc-b6e548fe.js → arc-bc141fb2.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-fa03ac9e.js → c4Diagram-d0fbc5ce-be2db283.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-ee67392a.js → classDiagram-936ed81e-55366915.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-9b283fae.js → classDiagram-v2-c3cb15f1-bb529518.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-8b6fcc2a.js → createText-62fc7601-b0ec81d6.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-22e77f4f.js → edges-f2ad444c-6166330c.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-60ffc87f.js → erDiagram-9d236eb7-5ccc6a8e.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9dd802e4.js → flowDb-1972c806-fca3bfe4.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-5fa1912f.js → flowDiagram-7ea5b25a-4739080f.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +1 -0
  46. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-622a1fd2.js → flowchart-elk-definition-abe16c3d-7c1b0e0f.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-e285a63a.js → ganttDiagram-9b5ea136-772fd050.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-f237bdca.js → gitGraphDiagram-99d0ae7c-8eae1dc9.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-4b03d70e.js → index-2c4b9a3b-f55afcdf.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/index-e7cef9de.js +1317 -0
  51. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-72a0fa5f.js → infoDiagram-736b4530-124d4a14.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-82218c41.js → journeyDiagram-df861f2b-7c4fae44.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{layout-78cff630.js → layout-b9885fb6.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{line-5038b469.js → line-7c59abb6.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{linear-c4fc4098.js → linear-4776f780.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-c33c8ea6.js → mindmap-definition-beec6740-2332c46c.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-a8d03059.js → pieDiagram-dbbf0591-8fb39303.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-6a0e56b2.js → quadrantDiagram-4d7f4fd6-3c7180a2.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-2dc7c7bd.js → requirementDiagram-6fc4c22a-e910bcb8.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-2360fe39.js → sankeyDiagram-8f13d901-ead16c89.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-41b9f9ad.js → sequenceDiagram-b655622a-29a02a19.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-0aad326f.js → stateDiagram-59f0c015-042b3137.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-9847d984.js → stateDiagram-v2-2b26beab-2178c0f3.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-564d890e.js → styles-080da4f6-23ffa4fc.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-38957613.js → styles-3dcbcfbf-94f59763.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-f0fc6921.js → styles-9c745c82-78a6bebc.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-ef3c5a77.js → svgDrawCommon-4835440b-eae2a6f6.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-bf3e91c1.js → timeline-definition-5b62e21b-5c968d92.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-4d4026c0.js → xychartDiagram-2b33534f-fd3db0d5.js} +1 -1
  70. rasa/core/channels/inspector/dist/index.html +18 -15
  71. rasa/core/channels/inspector/index.html +17 -14
  72. rasa/core/channels/inspector/package.json +5 -1
  73. rasa/core/channels/inspector/src/App.tsx +118 -68
  74. rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
  75. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +11 -10
  76. rasa/core/channels/inspector/src/components/DialogueStack.tsx +10 -25
  77. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -3
  78. rasa/core/channels/inspector/src/helpers/audiostream.ts +165 -0
  79. rasa/core/channels/inspector/src/helpers/formatters.test.ts +10 -0
  80. rasa/core/channels/inspector/src/helpers/formatters.ts +107 -41
  81. rasa/core/channels/inspector/src/helpers/utils.ts +92 -7
  82. rasa/core/channels/inspector/src/types.ts +21 -1
  83. rasa/core/channels/inspector/yarn.lock +94 -1
  84. rasa/core/channels/rest.py +51 -46
  85. rasa/core/channels/socketio.py +28 -1
  86. rasa/core/channels/telegram.py +1 -1
  87. rasa/core/channels/twilio.py +1 -1
  88. rasa/core/channels/{audiocodes.py → voice_ready/audiocodes.py} +122 -69
  89. rasa/core/channels/{voice_aware → voice_ready}/jambonz.py +26 -8
  90. rasa/core/channels/{voice_aware → voice_ready}/jambonz_protocol.py +57 -5
  91. rasa/core/channels/{twilio_voice.py → voice_ready/twilio_voice.py} +64 -28
  92. rasa/core/channels/voice_ready/utils.py +37 -0
  93. rasa/core/channels/voice_stream/asr/__init__.py +0 -0
  94. rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
  95. rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
  96. rasa/core/channels/voice_stream/asr/azure.py +129 -0
  97. rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
  98. rasa/core/channels/voice_stream/audio_bytes.py +8 -0
  99. rasa/core/channels/voice_stream/browser_audio.py +107 -0
  100. rasa/core/channels/voice_stream/call_state.py +23 -0
  101. rasa/core/channels/voice_stream/tts/__init__.py +0 -0
  102. rasa/core/channels/voice_stream/tts/azure.py +106 -0
  103. rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
  104. rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
  105. rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
  106. rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
  107. rasa/core/channels/voice_stream/util.py +57 -0
  108. rasa/core/channels/voice_stream/voice_channel.py +427 -0
  109. rasa/core/information_retrieval/qdrant.py +1 -0
  110. rasa/core/nlg/contextual_response_rephraser.py +45 -17
  111. rasa/{nlu → core}/persistor.py +203 -68
  112. rasa/core/policies/enterprise_search_policy.py +119 -63
  113. rasa/core/policies/flows/flow_executor.py +15 -22
  114. rasa/core/policies/intentless_policy.py +83 -28
  115. rasa/core/processor.py +25 -0
  116. rasa/core/run.py +12 -2
  117. rasa/core/secrets_manager/constants.py +4 -0
  118. rasa/core/secrets_manager/factory.py +8 -0
  119. rasa/core/secrets_manager/vault.py +11 -1
  120. rasa/core/training/interactive.py +33 -34
  121. rasa/core/utils.py +47 -21
  122. rasa/dialogue_understanding/coexistence/llm_based_router.py +41 -14
  123. rasa/dialogue_understanding/commands/__init__.py +6 -0
  124. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
  125. rasa/dialogue_understanding/commands/session_end_command.py +61 -0
  126. rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
  127. rasa/dialogue_understanding/commands/utils.py +5 -0
  128. rasa/dialogue_understanding/generator/constants.py +2 -0
  129. rasa/dialogue_understanding/generator/flow_retrieval.py +47 -9
  130. rasa/dialogue_understanding/generator/llm_based_command_generator.py +38 -15
  131. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  132. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +35 -13
  133. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +3 -0
  134. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +60 -13
  135. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +53 -0
  136. rasa/dialogue_understanding/patterns/repeat.py +37 -0
  137. rasa/dialogue_understanding/patterns/user_silence.py +37 -0
  138. rasa/dialogue_understanding/processor/command_processor.py +21 -1
  139. rasa/e2e_test/aggregate_test_stats_calculator.py +1 -11
  140. rasa/e2e_test/assertions.py +136 -61
  141. rasa/e2e_test/assertions_schema.yml +23 -0
  142. rasa/e2e_test/e2e_test_case.py +85 -6
  143. rasa/e2e_test/e2e_test_runner.py +2 -3
  144. rasa/engine/graph.py +0 -1
  145. rasa/engine/loader.py +12 -0
  146. rasa/engine/recipes/config_files/default_config.yml +0 -3
  147. rasa/engine/recipes/default_recipe.py +0 -1
  148. rasa/engine/recipes/graph_recipe.py +0 -1
  149. rasa/engine/runner/dask.py +2 -2
  150. rasa/engine/storage/local_model_storage.py +12 -42
  151. rasa/engine/storage/storage.py +1 -5
  152. rasa/engine/validation.py +527 -74
  153. rasa/model_manager/__init__.py +0 -0
  154. rasa/model_manager/config.py +40 -0
  155. rasa/model_manager/model_api.py +559 -0
  156. rasa/model_manager/runner_service.py +286 -0
  157. rasa/model_manager/socket_bridge.py +146 -0
  158. rasa/model_manager/studio_jwt_auth.py +86 -0
  159. rasa/model_manager/trainer_service.py +325 -0
  160. rasa/model_manager/utils.py +87 -0
  161. rasa/model_manager/warm_rasa_process.py +187 -0
  162. rasa/model_service.py +112 -0
  163. rasa/model_training.py +42 -23
  164. rasa/nlu/tokenizers/whitespace_tokenizer.py +3 -14
  165. rasa/server.py +4 -2
  166. rasa/shared/constants.py +60 -8
  167. rasa/shared/core/constants.py +13 -0
  168. rasa/shared/core/domain.py +107 -50
  169. rasa/shared/core/events.py +29 -0
  170. rasa/shared/core/flows/flow.py +5 -0
  171. rasa/shared/core/flows/flows_list.py +19 -6
  172. rasa/shared/core/flows/flows_yaml_schema.json +10 -0
  173. rasa/shared/core/flows/utils.py +39 -0
  174. rasa/shared/core/flows/validation.py +121 -0
  175. rasa/shared/core/flows/yaml_flows_io.py +15 -27
  176. rasa/shared/core/slots.py +5 -0
  177. rasa/shared/importers/importer.py +59 -41
  178. rasa/shared/importers/multi_project.py +23 -11
  179. rasa/shared/importers/rasa.py +12 -3
  180. rasa/shared/importers/remote_importer.py +196 -0
  181. rasa/shared/importers/utils.py +3 -1
  182. rasa/shared/nlu/training_data/formats/rasa_yaml.py +18 -3
  183. rasa/shared/nlu/training_data/training_data.py +18 -19
  184. rasa/shared/providers/_configs/litellm_router_client_config.py +220 -0
  185. rasa/shared/providers/_configs/model_group_config.py +167 -0
  186. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  187. rasa/shared/providers/_configs/rasa_llm_client_config.py +73 -0
  188. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -0
  189. rasa/shared/providers/_configs/utils.py +16 -0
  190. rasa/shared/providers/_utils.py +79 -0
  191. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +13 -29
  192. rasa/shared/providers/embedding/azure_openai_embedding_client.py +54 -21
  193. rasa/shared/providers/embedding/default_litellm_embedding_client.py +24 -0
  194. rasa/shared/providers/embedding/litellm_router_embedding_client.py +135 -0
  195. rasa/shared/providers/llm/_base_litellm_client.py +34 -22
  196. rasa/shared/providers/llm/azure_openai_llm_client.py +50 -29
  197. rasa/shared/providers/llm/default_litellm_llm_client.py +24 -0
  198. rasa/shared/providers/llm/litellm_router_llm_client.py +182 -0
  199. rasa/shared/providers/llm/rasa_llm_client.py +112 -0
  200. rasa/shared/providers/llm/self_hosted_llm_client.py +5 -29
  201. rasa/shared/providers/mappings.py +19 -0
  202. rasa/shared/providers/router/__init__.py +0 -0
  203. rasa/shared/providers/router/_base_litellm_router_client.py +183 -0
  204. rasa/shared/providers/router/router_client.py +73 -0
  205. rasa/shared/utils/common.py +40 -24
  206. rasa/shared/utils/health_check/__init__.py +0 -0
  207. rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
  208. rasa/shared/utils/health_check/health_check.py +258 -0
  209. rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
  210. rasa/shared/utils/io.py +27 -6
  211. rasa/shared/utils/llm.py +353 -43
  212. rasa/shared/utils/schemas/events.py +2 -0
  213. rasa/shared/utils/schemas/model_config.yml +0 -10
  214. rasa/shared/utils/yaml.py +181 -38
  215. rasa/studio/data_handler.py +3 -1
  216. rasa/studio/upload.py +160 -74
  217. rasa/telemetry.py +94 -17
  218. rasa/tracing/config.py +3 -1
  219. rasa/tracing/instrumentation/attribute_extractors.py +95 -18
  220. rasa/tracing/instrumentation/instrumentation.py +121 -0
  221. rasa/utils/common.py +5 -0
  222. rasa/utils/endpoints.py +27 -1
  223. rasa/utils/io.py +8 -16
  224. rasa/utils/log_utils.py +9 -2
  225. rasa/utils/sanic_error_handler.py +32 -0
  226. rasa/validator.py +110 -4
  227. rasa/version.py +1 -1
  228. {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/METADATA +14 -12
  229. {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/RECORD +234 -183
  230. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +0 -1
  231. rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +0 -1040
  232. rasa/core/channels/voice_aware/utils.py +0 -20
  233. rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +0 -407
  234. /rasa/core/channels/{voice_aware → voice_ready}/__init__.py +0 -0
  235. /rasa/core/channels/{voice_native → voice_stream}/__init__.py +0 -0
  236. {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/NOTICE +0 -0
  237. {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/WHEEL +0 -0
  238. {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/entry_points.txt +0 -0
rasa/shared/utils/llm.py CHANGED
@@ -1,4 +1,5 @@
1
- import sys
1
+ import json
2
+ from copy import deepcopy
2
3
  from functools import wraps
3
4
  from typing import (
4
5
  Any,
@@ -12,15 +13,19 @@ from typing import (
12
13
  Union,
13
14
  cast,
14
15
  )
15
- import json
16
16
 
17
17
  import structlog
18
18
 
19
19
  import rasa.shared.utils.io
20
+ from rasa.core.utils import AvailableEndpoints
20
21
  from rasa.shared.constants import (
21
22
  RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_TOO_LONG,
22
23
  RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_EMPTY,
23
24
  PROVIDER_CONFIG_KEY,
25
+ MODEL_GROUP_CONFIG_KEY,
26
+ MODEL_GROUP_ID_CONFIG_KEY,
27
+ MODELS_CONFIG_KEY,
28
+ ROUTER_CONFIG_KEY,
24
29
  )
25
30
  from rasa.shared.core.events import BotUttered, UserUttered
26
31
  from rasa.shared.core.slots import Slot, BooleanSlot, CategoricalSlot
@@ -30,7 +35,7 @@ from rasa.shared.engine.caching import (
30
35
  from rasa.shared.exceptions import (
31
36
  FileIOException,
32
37
  FileNotFoundException,
33
- ProviderClientValidationError,
38
+ InvalidConfigException,
34
39
  )
35
40
  from rasa.shared.providers._configs.azure_openai_client_config import (
36
41
  is_azure_openai_config,
@@ -57,6 +62,7 @@ from rasa.shared.providers.mappings import (
57
62
  if TYPE_CHECKING:
58
63
  from rasa.shared.core.trackers import DialogueStateTracker
59
64
 
65
+
60
66
  structlogger = structlog.get_logger()
61
67
 
62
68
  USER = "USER"
@@ -77,6 +83,8 @@ DEFAULT_OPENAI_MAX_GENERATED_TOKENS = 256
77
83
 
78
84
  DEFAULT_MAX_USER_INPUT_CHARACTERS = 420
79
85
 
86
+ DEPLOYMENT_CENTRIC_PROVIDERS = [AZURE_OPENAI_PROVIDER]
87
+
80
88
  # Placeholder messages used in the transcript for
81
89
  # instances where user input results in an error
82
90
  ERROR_PLACEHOLDER = {
@@ -245,7 +253,75 @@ def sanitize_message_for_prompt(text: Optional[str]) -> str:
245
253
  def combine_custom_and_default_config(
246
254
  custom_config: Optional[Dict[str, Any]], default_config: Dict[str, Any]
247
255
  ) -> Dict[Text, Any]:
248
- """Merges the given llm config with the default config.
256
+ """Merges the given model configuration with the default configuration.
257
+
258
+ This method supports both single model configurations and model group configurations
259
+ (configs that have the `models` key).
260
+
261
+ If `custom_config` is a single model configuration, it merges `custom_config` with
262
+ `default_config`, which is also a single model configuration.
263
+
264
+ If `custom_config` is a model group configuration (contains the `models` key), it
265
+ applies the merging process to each model configuration within the group
266
+ individually, merging each with the `default_config`.
267
+
268
+ Note that `default_config` is always a single model configuration.
269
+
270
+ The method ensures that the provider is set and all deprecated keys are resolved,
271
+ resulting in a valid client configuration.
272
+
273
+ Args:
274
+ custom_config: The custom configuration containing values to overwrite defaults.
275
+ Can be a single model configuration or a model group configuration with a
276
+ `models` key.
277
+ default_config: The default configuration, which is a single model
278
+ configuration.
279
+
280
+ Returns:
281
+ The merged configuration, either a single model configuration or a model group
282
+ configuration with merged models.
283
+ """
284
+ if custom_config and MODELS_CONFIG_KEY in custom_config:
285
+ return _combine_model_groups_configs_with_default_config(
286
+ custom_config, default_config
287
+ )
288
+ else:
289
+ return _combine_single_model_configs(custom_config, default_config)
290
+
291
+
292
+ def _combine_model_groups_configs_with_default_config(
293
+ model_group_config: Dict[str, Any], default_config: Dict[str, Any]
294
+ ) -> Dict[Text, Any]:
295
+ """Merges each model configuration within a model group with the default
296
+ configuration.
297
+
298
+ This method processes model group configurations by applying the merging process to
299
+ each model configuration within the group individually.
300
+
301
+ Args:
302
+ model_group_config: The model group configuration containing a list of model
303
+ configurations under the `models` key.
304
+ default_config: The default configuration for a single model.
305
+
306
+ Returns:
307
+ The merged model group configuration with each model configuration merged
308
+ with the default configuration.
309
+ """
310
+ model_group_config = deepcopy(model_group_config)
311
+ model_group_config_combined_with_defaults = [
312
+ _combine_single_model_configs(model_config, default_config)
313
+ for model_config in model_group_config[MODELS_CONFIG_KEY]
314
+ ]
315
+ # Update the custom models config with the combined config.
316
+ model_group_config[MODELS_CONFIG_KEY] = model_group_config_combined_with_defaults
317
+ return model_group_config
318
+
319
+
320
+ @_cache_combine_custom_and_default_configs
321
+ def _combine_single_model_configs(
322
+ custom_config: Optional[Dict[str, Any]], default_config: Dict[str, Any]
323
+ ) -> Dict[Text, Any]:
324
+ """Merges the given model config with the default config.
249
325
 
250
326
  This method guarantees that the provider is set and all the deprecated keys are
251
327
  resolved. Hence, produces only a valid client config.
@@ -330,6 +406,105 @@ def llm_factory(
330
406
  ) -> LLMClient:
331
407
  """Creates an LLM from the given config.
332
408
 
409
+ If the config is using the old syntax, e.g. defining the llm client directly in
410
+ config.yaml, then standalone client is initialised (no routing).
411
+
412
+ If the config uses the using the new, model group syntax, defined in the
413
+ endpoints.yml, then router client is initialised if there are more than one model
414
+ within the group.
415
+
416
+ Examples:
417
+ The config below will result in a standalone client:
418
+ ```
419
+ {
420
+ "provider": "openai",
421
+ "model": "gpt-4",
422
+ "timeout": 10,
423
+ "num_retries": 3,
424
+ }
425
+ ```
426
+
427
+ The config below will also result in a standalone client:
428
+ ```
429
+ {
430
+ "id": "model-group-id",
431
+ "models": [
432
+ {"provider": "openai", "model": "gpt-4", "api_key": "test"},
433
+ ],
434
+ }
435
+ ```
436
+
437
+ The config below will result in a router client:
438
+ ```
439
+ {
440
+ "id": "test-model-group-id",
441
+ "models": [
442
+ {"provider": "openai", "model": "gpt-4", "api_key": "test"},
443
+ {
444
+ "provider": "azure",
445
+ "deployment": "test-deployment",
446
+ "api_key": "test",
447
+ "api_base": "test-api-base",
448
+ },
449
+ ],
450
+ "router": {"routing_strategy": "test"},
451
+ }
452
+ ```
453
+
454
+ Args:
455
+ custom_config: The custom config containing values to overwrite defaults.
456
+ default_config: The default config.
457
+
458
+ Returns:
459
+ Instantiated client based on the configuration.
460
+ """
461
+ if custom_config:
462
+ if ROUTER_CONFIG_KEY in custom_config:
463
+ return llm_router_factory(custom_config, default_config)
464
+ if MODELS_CONFIG_KEY in custom_config:
465
+ return llm_client_factory(
466
+ custom_config[MODELS_CONFIG_KEY][0], default_config
467
+ )
468
+ return llm_client_factory(custom_config, default_config)
469
+
470
+
471
+ def llm_router_factory(
472
+ router_config: Dict[str, Any], default_model_config: Dict[str, Any], **kwargs: Any
473
+ ) -> LLMClient:
474
+ """Creates an LLM Router using the provided configurations.
475
+
476
+ This function initializes an LLM Router based on the given router configuration,
477
+ which includes multiple model configurations. For each model specified in the router
478
+ configuration, any missing parameters are supplemented using the default model
479
+ configuration.
480
+
481
+ Args:
482
+ router_config: The full router configuration containing multiple model
483
+ configurations. Each model's configuration can override parameters from the
484
+ default model configuration.
485
+ default_model_config: The default configuration parameters for a single model.
486
+ These defaults are used to fill in any missing parameters in each model's
487
+ configuration within the router.
488
+
489
+ Returns:
490
+ An instance that conforms to both `LLMClient` and `RouterClient` protocols
491
+ representing the configured LLM Router.
492
+ """
493
+ from rasa.shared.providers.llm.litellm_router_llm_client import (
494
+ LiteLLMRouterLLMClient,
495
+ )
496
+
497
+ combined_config = _combine_model_groups_configs_with_default_config(
498
+ router_config, default_model_config
499
+ )
500
+ return LiteLLMRouterLLMClient.from_config(combined_config)
501
+
502
+
503
+ def llm_client_factory(
504
+ custom_config: Optional[Dict[str, Any]], default_config: Dict[str, Any]
505
+ ) -> LLMClient:
506
+ """Creates an LLM from the given config.
507
+
333
508
  Args:
334
509
  custom_config: The custom config containing values to overwrite defaults
335
510
  default_config: The default config.
@@ -351,6 +526,110 @@ def llm_factory(
351
526
  @_cache_factory
352
527
  def embedder_factory(
353
528
  custom_config: Optional[Dict[str, Any]], default_config: Dict[str, Any]
529
+ ) -> EmbeddingClient:
530
+ """Creates an embedding client from the given config.
531
+
532
+ If the config is using the old syntax, e.g. defining the llm client directly in
533
+ config.yaml, then standalone client is initialised (no routing).
534
+
535
+ If the config uses the using the new, model group syntax, defined in the
536
+ endpoints.yml, then router client is initialised if there are more than one model
537
+ within the group and the router is defined.
538
+
539
+ Examples:
540
+ The config below will result in a standalone client:
541
+ ```
542
+ {
543
+ "provider": "openai",
544
+ "model": "text-embedding-3-small",
545
+ "timeout": 10,
546
+ "num_retries": 3,
547
+ }
548
+ ```
549
+
550
+ The config below will also result in a standalone client:
551
+ ```
552
+ {
553
+ "id": "model-group-id",
554
+ "models": [
555
+ {
556
+ "provider": "openai",
557
+ "model": "test-embedding-3-small",
558
+ "api_key": "test"
559
+ },
560
+ ],
561
+ }
562
+ ```
563
+
564
+ The config below will result in a router client:
565
+ ```
566
+ {
567
+ "id": "test-model-group-id",
568
+ "models": [
569
+ {"provider": "openai", "model": "gpt-4", "api_key": "test"},
570
+ {
571
+ "provider": "azure",
572
+ "deployment": "test-deployment",
573
+ "api_key": "test",
574
+ "api_base": "test-api-base",
575
+ },
576
+ ],
577
+ "router": {"routing_strategy": "test"},
578
+ }
579
+ ```
580
+
581
+ Args:
582
+ custom_config: The custom config containing values to overwrite defaults.
583
+ default_config: The default config.
584
+
585
+ Returns:
586
+ Instantiated client based on the configuration.
587
+ """
588
+ if custom_config:
589
+ if ROUTER_CONFIG_KEY in custom_config:
590
+ return embedder_router_factory(custom_config, default_config)
591
+ if MODELS_CONFIG_KEY in custom_config:
592
+ return embedder_client_factory(
593
+ custom_config[MODELS_CONFIG_KEY][0], default_config
594
+ )
595
+ return embedder_client_factory(custom_config, default_config)
596
+
597
+
598
+ def embedder_router_factory(
599
+ router_config: Dict[str, Any], default_model_config: Dict[str, Any], **kwargs: Any
600
+ ) -> EmbeddingClient:
601
+ """Creates an Embedder Router using the provided configurations.
602
+
603
+ This function initializes an Embedder Router based on the given router
604
+ configuration, which includes multiple model configurations. For each model
605
+ specified in the router configuration, any missing parameters are supplemented using
606
+ the default model configuration.
607
+
608
+ Args:
609
+ router_config: The full router configuration containing multiple model
610
+ configurations. Each model's configuration can override parameters from the
611
+ default model configuration.
612
+ default_model_config: The default configuration parameters for a single model.
613
+ These defaults are used to fill in any missing parameters in each model's
614
+ configuration within the router.
615
+
616
+ Returns:
617
+ An instance that conforms to both `EmbeddingClient` and `RouterClient` protocols
618
+ representing the configured Embedding Router.
619
+ """
620
+ from rasa.shared.providers.embedding.litellm_router_embedding_client import (
621
+ LiteLLMRouterEmbeddingClient,
622
+ )
623
+
624
+ combined_config = _combine_model_groups_configs_with_default_config(
625
+ router_config, default_model_config
626
+ )
627
+
628
+ return LiteLLMRouterEmbeddingClient.from_config(combined_config)
629
+
630
+
631
+ def embedder_client_factory(
632
+ custom_config: Optional[Dict[str, Any]], default_config: Dict[str, Any]
354
633
  ) -> EmbeddingClient:
355
634
  """Creates an Embedder from the given config.
356
635
 
@@ -406,45 +685,76 @@ def allowed_values_for_slot(slot: Slot) -> Union[str, None]:
406
685
  return None
407
686
 
408
687
 
409
- def try_instantiate_llm_client(
410
- custom_llm_config: Optional[Dict],
411
- default_llm_config: Optional[Dict],
412
- log_source_function: str,
413
- log_source_component: str,
414
- ) -> None:
415
- """Validate llm configuration."""
416
- try:
417
- llm_factory(custom_llm_config, default_llm_config)
418
- except (ProviderClientValidationError, ValueError) as e:
419
- structlogger.error(
420
- f"{log_source_function}.llm_instantiation_failed",
421
- event_info=(
422
- f"Unable to create the LLM client for component - "
423
- f"{log_source_component}. Please make sure you specified the required "
424
- f"environment variables and configuration keys."
425
- ),
426
- error=e,
427
- )
428
- sys.exit(1)
688
+ def resolve_model_client_config(
689
+ model_config: Optional[Dict[str, Any]], component_name: Optional[str] = None
690
+ ) -> Optional[Dict[str, Any]]:
691
+ """Resolve the model group in the model config.
429
692
 
693
+ 1. If the config is pointing to a model group, the corresponding model group
694
+ of the endpoints.yml is returned.
695
+ 2. If the config is using the old syntax, e.g. defining the llm
696
+ directly in config.yml, the config is returned as is.
697
+ 3. If the config is already resolved, return it as is.
430
698
 
431
- def try_instantiate_embedder(
432
- custom_embeddings_config: Optional[Dict],
433
- default_embeddings_config: Optional[Dict],
434
- log_source_function: str,
435
- log_source_component: str,
436
- ) -> EmbeddingClient:
437
- """Validate embeddings configuration."""
438
- try:
439
- return embedder_factory(custom_embeddings_config, default_embeddings_config)
440
- except (ProviderClientValidationError, ValueError) as e:
441
- structlogger.error(
442
- f"{log_source_function}.embedder_instantiation_failed",
443
- event_info=(
444
- f"Unable to create the Embedding client for component - "
445
- f"{log_source_component}. Please make sure you specified the required "
446
- f"environment variables and configuration keys."
447
- ),
448
- error=e,
699
+ Args:
700
+ model_config: The model config to be resolved.
701
+ component_name: The name of the component.
702
+ component_name: The method of the component.
703
+
704
+ Returns:
705
+ The resolved llm config.
706
+ """
707
+
708
+ def _raise_invalid_config_exception(reason: str) -> None:
709
+ """Helper function to raise InvalidConfigException with a formatted message."""
710
+ if component_name:
711
+ message = (
712
+ f"Could not resolve model group '{model_group_id}'"
713
+ f" for component '{component_name}'."
714
+ )
715
+ else:
716
+ message = f"Could not resolve model group '{model_group_id}'."
717
+ message += f" {reason}"
718
+ raise InvalidConfigException(message)
719
+
720
+ if model_config is None:
721
+ return None
722
+
723
+ # Config is already resolved or defines a client without model groups
724
+ if MODEL_GROUP_CONFIG_KEY not in model_config:
725
+ return model_config
726
+
727
+ model_group_id = model_config.get(MODEL_GROUP_CONFIG_KEY)
728
+
729
+ endpoints = AvailableEndpoints.get_instance()
730
+ if endpoints.model_groups is None:
731
+ _raise_invalid_config_exception(
732
+ reason=(
733
+ "No model group with that id found in endpoints.yml. "
734
+ "Please make sure to define the model group."
735
+ )
736
+ )
737
+
738
+ copy_model_groups = deepcopy(endpoints.model_groups)
739
+ model_group = [
740
+ model_group
741
+ for model_group in copy_model_groups # type: ignore[union-attr]
742
+ if model_group.get(MODEL_GROUP_ID_CONFIG_KEY) == model_group_id
743
+ ]
744
+
745
+ if len(model_group) == 0:
746
+ _raise_invalid_config_exception(
747
+ reason=(
748
+ "No model group with that id found in endpoints.yml. "
749
+ "Please make sure to define the model group."
750
+ )
449
751
  )
450
- sys.exit(1)
752
+ if len(model_group) > 1:
753
+ _raise_invalid_config_exception(
754
+ reason=(
755
+ "Multiple model groups with that id found in endpoints.yml. "
756
+ "Please make sure to define the model group just once."
757
+ )
758
+ )
759
+
760
+ return model_group[0]
@@ -127,6 +127,7 @@ ACTION_REVERTED = {"properties": {"event": {"const": "undo"}}}
127
127
  USER_UTTERANCE_REVERTED = {"properties": {"event": {"const": "rewind"}}}
128
128
  BOT_UTTERED = {"properties": {"event": {"const": "bot"}}}
129
129
  SESSION_STARTED = {"properties": {"event": {"const": "session_started"}}}
130
+ SESSION_ENDED = {"properties": {"event": {"const": "session_ended"}}}
130
131
  AGENT_UTTERED = {"properties": {"event": {"const": "agent"}}}
131
132
  FLOW_STARTED = {
132
133
  "properties": {"event": {"const": "flow_started"}, "flow_id": {"type": "string"}}
@@ -206,6 +207,7 @@ EVENT_SCHEMA = {
206
207
  FLOW_CANCELLED,
207
208
  DIALOGUE_STACK_UPDATED,
208
209
  ROUTING_SESSION_ENDED,
210
+ SESSION_ENDED,
209
211
  ],
210
212
  }
211
213
 
@@ -34,13 +34,3 @@ mapping:
34
34
  name:
35
35
  type: str
36
36
  required: True
37
- spaces:
38
- type: "seq"
39
- required: False
40
- sequence:
41
- - type: "map"
42
- allowempty: True
43
- mapping:
44
- name:
45
- type: str
46
- required: True