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
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, Union
5
5
 
6
6
  import tiktoken
7
7
  from numpy import ndarray
8
+ from rasa.dialogue_understanding.generator.constants import FLOW_RETRIEVAL_KEY
8
9
  from rasa_sdk.grpc_py import action_webhook_pb2
9
10
 
10
11
  from rasa.core.actions.action import DirectCustomActionExecutor
@@ -19,6 +20,7 @@ from rasa.core.processor import MessageProcessor
19
20
  from rasa.core.tracker_store import TrackerStore
20
21
  from rasa.dialogue_understanding.commands import Command
21
22
  from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
23
+ from rasa.dialogue_understanding.generator import LLMBasedCommandGenerator
22
24
  from rasa.engine.graph import ExecutionContext, GraphModelConfiguration, GraphNode
23
25
  from rasa.engine.training.graph_trainer import GraphTrainer
24
26
  from rasa.shared.constants import (
@@ -27,6 +29,8 @@ from rasa.shared.constants import (
27
29
  PROVIDER_CONFIG_KEY,
28
30
  TIMEOUT_CONFIG_KEY,
29
31
  DEPLOYMENT_CONFIG_KEY,
32
+ MODEL_GROUP_ID_CONFIG_KEY,
33
+ LLM_CONFIG_KEY,
30
34
  )
31
35
  from rasa.shared.core.constants import REQUESTED_SLOT
32
36
  from rasa.shared.core.domain import Domain
@@ -50,10 +54,7 @@ if TYPE_CHECKING:
50
54
  from rasa.core.policies.enterprise_search_policy import EnterpriseSearchPolicy
51
55
  from rasa.core.policies.intentless_policy import IntentlessPolicy
52
56
  from rasa.core.policies.policy import PolicyPrediction
53
- from rasa.dialogue_understanding.generator import (
54
- CommandGenerator,
55
- LLMBasedCommandGenerator,
56
- )
57
+ from rasa.dialogue_understanding.generator import CommandGenerator
57
58
 
58
59
  # This file contains all attribute extractors for tracing instrumentation.
59
60
  # These are functions that are applied to the arguments of the wrapped function to be
@@ -300,22 +301,49 @@ def extract_attrs_for_command(
300
301
  }
301
302
 
302
303
 
303
- def extract_llm_config(self: Any, default_llm_config: Dict[str, Any]) -> Dict[str, Any]:
304
+ def extract_llm_config(
305
+ self: Any,
306
+ default_llm_config: Dict[str, Any],
307
+ default_embeddings_config: Dict[str, Any],
308
+ ) -> Dict[str, Any]:
304
309
  if isinstance(self, ContextualResponseRephraser):
305
- config = self.nlg_endpoint.kwargs
310
+ # ContextualResponseRephraser is not a graph component, so it's
311
+ # not having a full config.
312
+ config = {"llm": self.llm_config}
306
313
  else:
307
314
  config = self.config
308
315
 
309
316
  llm_property = combine_custom_and_default_config(
310
- config.get("llm"), default_llm_config
317
+ config.get(LLM_CONFIG_KEY), default_llm_config
311
318
  )
312
319
 
320
+ if isinstance(self, LLMBasedCommandGenerator):
321
+ flow_retrieval_config = config.get(FLOW_RETRIEVAL_KEY, {}) or {}
322
+ embeddings_property = combine_custom_and_default_config(
323
+ flow_retrieval_config.get(EMBEDDINGS_CONFIG_KEY),
324
+ default_embeddings_config,
325
+ )
326
+ else:
327
+ embeddings_property = combine_custom_and_default_config(
328
+ config.get(EMBEDDINGS_CONFIG_KEY), default_embeddings_config
329
+ )
330
+
313
331
  attributes = {
314
332
  "class_name": self.__class__.__name__,
333
+ # llm client attributes
315
334
  "llm_model": str(llm_property.get(MODEL_CONFIG_KEY)),
316
335
  "llm_type": str(llm_property.get(PROVIDER_CONFIG_KEY)),
317
- "embeddings": json.dumps(config.get(EMBEDDINGS_CONFIG_KEY, {})),
336
+ "llm_model_group_id": str(llm_property.get(MODEL_GROUP_ID_CONFIG_KEY)),
318
337
  "llm_temperature": str(llm_property.get("temperature")),
338
+ "llm_request_timeout": str(llm_property.get(TIMEOUT_CONFIG_KEY)),
339
+ # embedding client attributes
340
+ "embeddings_model": str(embeddings_property.get(MODEL_CONFIG_KEY)),
341
+ "embeddings_type": str(embeddings_property.get(PROVIDER_CONFIG_KEY)),
342
+ "embeddings_model_group_id": str(
343
+ embeddings_property.get(MODEL_GROUP_ID_CONFIG_KEY)
344
+ ),
345
+ # TODO: Keeping this to avoid potential breaking changes
346
+ "embeddings": json.dumps(embeddings_property, sort_keys=True),
319
347
  "request_timeout": str(llm_property.get(TIMEOUT_CONFIG_KEY)),
320
348
  }
321
349
 
@@ -329,11 +357,16 @@ def extract_attrs_for_llm_based_command_generator(
329
357
  self: "LLMBasedCommandGenerator",
330
358
  prompt: str,
331
359
  ) -> Dict[str, Any]:
332
- from rasa.dialogue_understanding.generator.constants import (
333
- DEFAULT_LLM_CONFIG,
360
+ from rasa.dialogue_understanding.generator.constants import DEFAULT_LLM_CONFIG
361
+ from rasa.dialogue_understanding.generator.flow_retrieval import (
362
+ DEFAULT_EMBEDDINGS_CONFIG,
334
363
  )
335
364
 
336
- attributes = extract_llm_config(self, default_llm_config=DEFAULT_LLM_CONFIG)
365
+ attributes = extract_llm_config(
366
+ self,
367
+ default_llm_config=DEFAULT_LLM_CONFIG,
368
+ default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
369
+ )
337
370
 
338
371
  return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
339
372
 
@@ -344,7 +377,12 @@ def extract_attrs_for_contextual_response_rephraser(
344
377
  ) -> Dict[str, Any]:
345
378
  from rasa.core.nlg.contextual_response_rephraser import DEFAULT_LLM_CONFIG
346
379
 
347
- attributes = extract_llm_config(self, default_llm_config=DEFAULT_LLM_CONFIG)
380
+ attributes = extract_llm_config(
381
+ self,
382
+ default_llm_config=DEFAULT_LLM_CONFIG,
383
+ # rephraser is not using embeddings
384
+ default_embeddings_config={},
385
+ )
348
386
 
349
387
  return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
350
388
 
@@ -355,7 +393,12 @@ def extract_attrs_for_create_history(
355
393
  ) -> Dict[str, Any]:
356
394
  from rasa.core.nlg.contextual_response_rephraser import DEFAULT_LLM_CONFIG
357
395
 
358
- return extract_llm_config(self, default_llm_config=DEFAULT_LLM_CONFIG)
396
+ return extract_llm_config(
397
+ self,
398
+ default_llm_config=DEFAULT_LLM_CONFIG,
399
+ # rephraser is not using embeddings
400
+ default_embeddings_config={},
401
+ )
359
402
 
360
403
 
361
404
  def extract_attrs_for_generate(
@@ -371,6 +414,26 @@ def extract_attrs_for_generate(
371
414
  }
372
415
 
373
416
 
417
+ def extract_attrs_for_performing_health_check(
418
+ custom_config: Optional[Dict[str, Any]],
419
+ default_config: Dict[str, Any],
420
+ log_source_method: str,
421
+ log_source_component: str,
422
+ ) -> Dict[str, Any]:
423
+ from rasa.shared.utils.health_check.health_check import is_api_health_check_enabled
424
+
425
+ attrs = {
426
+ "api_health_check_enabled": is_api_health_check_enabled(),
427
+ "health_check_trigger_component": log_source_component,
428
+ "health_check_trigger_method": log_source_method,
429
+ }
430
+ if is_api_health_check_enabled():
431
+ attrs["config"] = json.dumps(
432
+ combine_custom_and_default_config(custom_config, default_config)
433
+ )
434
+ return attrs
435
+
436
+
374
437
  def extract_attrs_for_execute_commands(
375
438
  tracker: DialogueStateTracker,
376
439
  all_flows: FlowsList,
@@ -580,9 +643,16 @@ def extract_attrs_for_intentless_policy_find_closest_response(
580
643
  def extract_attrs_for_intentless_policy_generate_llm_answer(
581
644
  self: "IntentlessPolicy", llm: "BaseLLM", prompt: str
582
645
  ) -> Dict[str, Any]:
583
- from rasa.core.policies.intentless_policy import DEFAULT_LLM_CONFIG
646
+ from rasa.core.policies.intentless_policy import (
647
+ DEFAULT_LLM_CONFIG,
648
+ DEFAULT_EMBEDDINGS_CONFIG,
649
+ )
584
650
 
585
- attributes = extract_llm_config(self, default_llm_config=DEFAULT_LLM_CONFIG)
651
+ attributes = extract_llm_config(
652
+ self,
653
+ default_llm_config=DEFAULT_LLM_CONFIG,
654
+ default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
655
+ )
586
656
 
587
657
  return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
588
658
 
@@ -590,9 +660,16 @@ def extract_attrs_for_intentless_policy_generate_llm_answer(
590
660
  def extract_attrs_for_enterprise_search_generate_llm_answer(
591
661
  self: "EnterpriseSearchPolicy", llm: "BaseLLM", prompt: str
592
662
  ) -> Dict[str, Any]:
593
- from rasa.core.policies.enterprise_search_policy import DEFAULT_LLM_CONFIG
663
+ from rasa.core.policies.enterprise_search_policy import (
664
+ DEFAULT_LLM_CONFIG,
665
+ DEFAULT_EMBEDDINGS_CONFIG,
666
+ )
594
667
 
595
- attributes = extract_llm_config(self, default_llm_config=DEFAULT_LLM_CONFIG)
668
+ attributes = extract_llm_config(
669
+ self,
670
+ default_llm_config=DEFAULT_LLM_CONFIG,
671
+ default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
672
+ )
596
673
 
597
674
  return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
598
675
 
@@ -664,7 +741,7 @@ def extract_attrs_for_custom_action_executor_run(
664
741
 
665
742
  attrs: Dict[str, Any] = {
666
743
  "class_name": self.__class__.__name__,
667
- "action_name": self.action_name,
744
+ "action_name": self.action_name if hasattr(self, "action_name") else "None",
668
745
  "sender_id": tracker.sender_id,
669
746
  "url": str(url),
670
747
  "actions_module": str(actions_module),
@@ -45,6 +45,7 @@ from rasa.dialogue_understanding.generator import (
45
45
  MultiStepLLMCommandGenerator,
46
46
  SingleStepLLMCommandGenerator,
47
47
  )
48
+ from rasa.dialogue_understanding.generator.flow_retrieval import FlowRetrieval
48
49
  from rasa.dialogue_understanding.generator.nlu_command_adapter import NLUCommandAdapter
49
50
  from rasa.engine.graph import GraphNode
50
51
  from rasa.engine.training.graph_trainer import GraphTrainer
@@ -283,6 +284,7 @@ SingleStepLLMCommandGeneratorType = TypeVar(
283
284
  MultiStepLLMCommandGeneratorType = TypeVar(
284
285
  "MultiStepLLMCommandGeneratorType", bound=MultiStepLLMCommandGenerator
285
286
  )
287
+ FlowRetrievalType = TypeVar("FlowRetrievalType", bound=FlowRetrieval)
286
288
  CommandType = TypeVar("CommandType", bound=Command)
287
289
  PolicyType = TypeVar("PolicyType", bound=Policy)
288
290
  InformationRetrievalType = TypeVar(
@@ -317,6 +319,7 @@ def instrument(
317
319
  custom_action_executor_subclasses: Optional[
318
320
  List[Type[CustomActionExecutor]]
319
321
  ] = None,
322
+ flow_retrieval_class: Optional[Type[FlowRetrievalType]] = None,
320
323
  ) -> None:
321
324
  """Substitute methods to be traced by their traced counterparts.
322
325
 
@@ -445,6 +448,12 @@ def instrument(
445
448
  "_check_commands_against_startable_flows",
446
449
  attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
447
450
  )
451
+ _instrument_perform_health_check_method_for_component(
452
+ tracer_provider.get_tracer(llm_command_generator_class.__module__),
453
+ llm_command_generator_class,
454
+ "perform_llm_health_check",
455
+ attribute_extractors.extract_attrs_for_performing_health_check,
456
+ )
448
457
  mark_class_as_instrumented(llm_command_generator_class)
449
458
 
450
459
  if (
@@ -468,6 +477,14 @@ def instrument(
468
477
  "_check_commands_against_startable_flows",
469
478
  attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
470
479
  )
480
+ _instrument_perform_health_check_method_for_component(
481
+ tracer_provider.get_tracer(
482
+ single_step_llm_command_generator_class.__module__
483
+ ),
484
+ single_step_llm_command_generator_class,
485
+ "perform_llm_health_check",
486
+ attribute_extractors.extract_attrs_for_performing_health_check,
487
+ )
471
488
  mark_class_as_instrumented(single_step_llm_command_generator_class)
472
489
 
473
490
  if multi_step_llm_command_generator_class is not None and not class_is_instrumented(
@@ -488,8 +505,36 @@ def instrument(
488
505
  ),
489
506
  multi_step_llm_command_generator_class,
490
507
  )
508
+ _instrument_perform_health_check_method_for_component(
509
+ tracer_provider.get_tracer(
510
+ multi_step_llm_command_generator_class.__module__
511
+ ),
512
+ multi_step_llm_command_generator_class,
513
+ "perform_llm_health_check",
514
+ attribute_extractors.extract_attrs_for_performing_health_check,
515
+ )
491
516
  mark_class_as_instrumented(multi_step_llm_command_generator_class)
492
517
 
518
+ if (
519
+ any(
520
+ llm_based_command_generator_class is not None
521
+ for llm_based_command_generator_class in (
522
+ llm_command_generator_class,
523
+ single_step_llm_command_generator_class,
524
+ multi_step_llm_command_generator_class,
525
+ )
526
+ )
527
+ and flow_retrieval_class is not None
528
+ and not class_is_instrumented(flow_retrieval_class)
529
+ ):
530
+ _instrument_perform_health_check_method_for_component(
531
+ tracer_provider.get_tracer(flow_retrieval_class.__module__),
532
+ flow_retrieval_class,
533
+ "perform_embeddings_health_check",
534
+ attribute_extractors.extract_attrs_for_performing_health_check,
535
+ )
536
+ mark_class_as_instrumented(flow_retrieval_class)
537
+
493
538
  if command_subclasses:
494
539
  for command_subclass in command_subclasses:
495
540
  if command_subclass is not None and not class_is_instrumented(
@@ -524,6 +569,12 @@ def instrument(
524
569
  "generate",
525
570
  attribute_extractors.extract_attrs_for_generate,
526
571
  )
572
+ _instrument_perform_health_check_method_for_component(
573
+ tracer_provider.get_tracer(contextual_response_rephraser_class.__module__),
574
+ contextual_response_rephraser_class,
575
+ "perform_llm_health_check",
576
+ attribute_extractors.extract_attrs_for_performing_health_check,
577
+ )
527
578
  mark_class_as_instrumented(contextual_response_rephraser_class)
528
579
 
529
580
  if not module_is_instrumented(COMMAND_PROCESSOR_MODULE_NAME):
@@ -755,6 +806,18 @@ def _instrument_enterprise_search_policy(
755
806
  "_generate_llm_answer",
756
807
  attribute_extractors.extract_attrs_for_enterprise_search_generate_llm_answer,
757
808
  )
809
+ _instrument_perform_health_check_method_for_component(
810
+ tracer_provider.get_tracer(policy_class.__module__),
811
+ policy_class,
812
+ "perform_embeddings_health_check",
813
+ attribute_extractors.extract_attrs_for_performing_health_check,
814
+ )
815
+ _instrument_perform_health_check_method_for_component(
816
+ tracer_provider.get_tracer(policy_class.__module__),
817
+ policy_class,
818
+ "perform_llm_health_check",
819
+ attribute_extractors.extract_attrs_for_performing_health_check,
820
+ )
758
821
 
759
822
 
760
823
  def _instrument_intentless_policy(
@@ -787,6 +850,18 @@ def _instrument_intentless_policy(
787
850
  "_generate_llm_answer",
788
851
  attribute_extractors.extract_attrs_for_intentless_policy_generate_llm_answer,
789
852
  )
853
+ _instrument_perform_health_check_method_for_component(
854
+ tracer_provider.get_tracer(policy_class.__module__),
855
+ policy_class,
856
+ "perform_embeddings_health_check",
857
+ attribute_extractors.extract_attrs_for_performing_health_check,
858
+ )
859
+ _instrument_perform_health_check_method_for_component(
860
+ tracer_provider.get_tracer(policy_class.__module__),
861
+ policy_class,
862
+ "perform_llm_health_check",
863
+ attribute_extractors.extract_attrs_for_performing_health_check,
864
+ )
790
865
 
791
866
 
792
867
  def _instrument_processor(
@@ -1139,6 +1214,52 @@ def _instrument_grpc_custom_action_executor(
1139
1214
  logger.debug(f"Instrumented '{grpc_custom_action_executor_class.__name__}.run.")
1140
1215
 
1141
1216
 
1217
+ def _instrument_perform_health_check_method_for_component(
1218
+ tracer: Tracer,
1219
+ instrumented_class: Type,
1220
+ method_name: Text,
1221
+ attr_extractor: Optional[Callable] = None,
1222
+ return_value_attr_extractor: Optional[Callable] = None,
1223
+ ) -> None:
1224
+ def tracing_perform_health_check_for_component(
1225
+ fn: Callable[..., S],
1226
+ ) -> Callable[..., S]:
1227
+ @functools.wraps(fn)
1228
+ def wrapper(*args: Any, **kwargs: Any) -> S:
1229
+ # Check the first argument to adjust for self/cls depending on how
1230
+ # the static method from LLMHealthCheckMixin / EmbeddingsLLMHealthCheckMixin
1231
+ # is called.
1232
+ if args and isinstance(
1233
+ args[0], (instrumented_class, type(instrumented_class))
1234
+ ):
1235
+ # The first argument is self/cls; align args to match the signature
1236
+ args = args[1:]
1237
+
1238
+ span_name = f"{instrumented_class.__name__}.{fn.__name__}"
1239
+ extracted_attrs = attr_extractor(*args, **kwargs) if attr_extractor else {}
1240
+
1241
+ with tracer.start_as_current_span(span_name) as span:
1242
+ result = fn(*args, **kwargs)
1243
+
1244
+ # Extract attributes from the return value, if an extractor is provided
1245
+ return_value_attributes = (
1246
+ return_value_attr_extractor(result, *args, **kwargs)
1247
+ if return_value_attr_extractor
1248
+ else {}
1249
+ )
1250
+
1251
+ span.set_attributes({**extracted_attrs, **return_value_attributes})
1252
+ return result
1253
+
1254
+ return wrapper
1255
+
1256
+ method_to_trace = getattr(instrumented_class, method_name)
1257
+ traced_method = tracing_perform_health_check_for_component(method_to_trace)
1258
+ setattr(instrumented_class, method_name, traced_method)
1259
+
1260
+ logger.debug(f"Instrumented '{instrumented_class.__name__}.{method_name}'.")
1261
+
1262
+
1142
1263
  def _mangled_instrumented_boolean_attribute_name(instrumented_class: Type) -> Text:
1143
1264
  # see https://peps.python.org/pep-0008/#method-names-and-instance-variables
1144
1265
  # and https://stackoverflow.com/a/50401073
rasa/utils/common.py CHANGED
@@ -90,6 +90,11 @@ EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
90
90
  # Ignore Keras DeprecationWarning since it requires that we
91
91
  # upgrade tensorflow-macos to 2.13.0 version.
92
92
  (DeprecationWarning, "invalid escape sequence*"),
93
+ # Ignore importlib open_text and read_text warnings for now
94
+ (
95
+ DeprecationWarning,
96
+ "https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy",
97
+ ),
93
98
  ]
94
99
 
95
100
  PYTHON_LOGGING_SCHEMA_DOCS = (
rasa/utils/endpoints.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import ssl
3
3
  from types import ModuleType
4
- from typing import Any, Optional, Text, Dict, Union
4
+ from typing import Any, List, Optional, Text, Dict, Union
5
5
 
6
6
  import aiohttp
7
7
  import structlog
@@ -41,6 +41,32 @@ def read_endpoint_config(
41
41
  return None
42
42
 
43
43
 
44
+ def read_property_config_from_endpoints_file(
45
+ filename: str, property_name: str
46
+ ) -> Optional[Union[Dict[str, Any], List]]:
47
+ """Read a property from an endpoint configuration file."""
48
+ if not filename:
49
+ return None
50
+
51
+ try:
52
+ content = read_config_file(filename)
53
+
54
+ if content.get(property_name) is None:
55
+ return None
56
+
57
+ return content[property_name]
58
+ except FileNotFoundError:
59
+ structlogger.error(
60
+ "endpoint.read.failed_no_such_file",
61
+ filename=os.path.abspath(filename),
62
+ event_info=(
63
+ "Failed to read endpoint configuration file - "
64
+ "the file was not found."
65
+ ),
66
+ )
67
+ return None
68
+
69
+
44
70
  def concat_url(base: Text, subpath: Optional[Text]) -> Text:
45
71
  """Append a subpath to a base url.
46
72
 
rasa/utils/io.py CHANGED
@@ -18,7 +18,6 @@ from typing import (
18
18
  Type,
19
19
  Callable,
20
20
  TYPE_CHECKING,
21
- Pattern,
22
21
  )
23
22
 
24
23
  from ruamel import yaml
@@ -167,21 +166,14 @@ def create_validator(
167
166
  return FunctionValidator
168
167
 
169
168
 
170
- def get_emoji_regex() -> Pattern:
171
- """Returns regex to identify emojis."""
172
- return re.compile(
173
- "["
174
- "\U0001f600-\U0001f64f" # emoticons
175
- "\U0001f300-\U0001f5ff" # symbols & pictographs
176
- "\U0001f680-\U0001f6ff" # transport & map symbols
177
- "\U0001f1e0-\U0001f1ff" # flags (iOS)
178
- "\U00002702-\U000027b0"
179
- "\U000024c2-\U0001f251"
180
- "\u200d" # zero width joiner
181
- "\u200c" # zero width non-joiner
182
- "]+",
183
- flags=re.UNICODE,
184
- )
169
+ def remove_emojis(s: str) -> str:
170
+ import demoji
171
+
172
+ replaced = demoji.replace(s)
173
+ if replaced == s:
174
+ return s
175
+ # remove duplicate or trailing whitespaces if emojis were removed
176
+ return re.sub(r" +", " ", replaced).strip()
185
177
 
186
178
 
187
179
  def are_directories_equal(dir1: Path, dir2: Path) -> bool:
rasa/utils/log_utils.py CHANGED
@@ -78,6 +78,7 @@ def _anonymizer(
78
78
 
79
79
  def configure_structlog(
80
80
  log_level: Optional[int] = None,
81
+ include_time: bool = False,
81
82
  ) -> None:
82
83
  """Configure logging of the server."""
83
84
  if log_level is None: # Log level NOTSET is 0 so we use `is None` here
@@ -114,6 +115,9 @@ def configure_structlog(
114
115
  SentryProcessor(event_level=logging.FATAL),
115
116
  ]
116
117
 
118
+ if include_time:
119
+ shared_processors.append(structlog.processors.TimeStamper(fmt="iso"))
120
+
117
121
  if not FORCE_JSON_LOGGING and sys.stderr.isatty():
118
122
  # Pretty printing when we run in a terminal session.
119
123
  # Automatically prints pretty tracebacks when "rich" is installed
@@ -143,11 +147,14 @@ def configure_structlog(
143
147
  # logger.
144
148
  cache_logger_on_first_use=True,
145
149
  )
150
+ # doing logger creation inline, to prevent usage of unconfigured logger
151
+ structlog.get_logger().debug("structlog.configured")
146
152
 
147
153
 
148
154
  def log_llm(logger: Any, log_module: str, log_event: str, **kwargs: Any) -> None:
149
- """Logs LLM-specific events depending on a flag passed through an environment
150
- variable. If the module's flag is set to INFO (e.g.
155
+ """Logs LLM-specific events depending on a flag passed through an env var.
156
+
157
+ If the module's flag is set to INFO (e.g.
151
158
  LOG_PROMPT_LLM_COMMAND_GENERATOR=INFO), its prompt is logged at INFO level,
152
159
  overriding the general log level setting.
153
160
 
@@ -0,0 +1,32 @@
1
+ from sanic import Sanic
2
+ from sanic.handlers import ErrorHandler
3
+ from sanic.request import Request
4
+ from sanic.exceptions import ServerError
5
+
6
+
7
+ # TODO: remove custom handler when upgrading to sanic >= 24
8
+ # the underlying issue https://github.com/sanic-org/sanic/issues/2572
9
+ # has been fixed in sanic 24
10
+ class IgnoreWSServerErrorHandler(ErrorHandler):
11
+ @staticmethod
12
+ def log(request: Request, exception: Exception) -> None:
13
+ try:
14
+ if (
15
+ request.url.startswith("ws")
16
+ and isinstance(exception, ServerError)
17
+ and exception.args
18
+ and (
19
+ exception.args[0]
20
+ == "Invalid response type None (need HTTPResponse)"
21
+ )
22
+ ):
23
+ # in case we are in a websocket connection, we don't want to log the
24
+ # the error, as this is a bug in sanic
25
+ return
26
+ except Exception:
27
+ pass
28
+ ErrorHandler.log(request, exception) # type: ignore
29
+
30
+
31
+ def register_custom_sanic_error_handler(app: Sanic) -> None:
32
+ app.error_handler = IgnoreWSServerErrorHandler()