rasa-pro 3.11.0__py3-none-any.whl → 3.11.0a2__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 (217) hide show
  1. README.md +396 -17
  2. rasa/__main__.py +15 -31
  3. rasa/api.py +1 -5
  4. rasa/cli/arguments/default_arguments.py +2 -1
  5. rasa/cli/arguments/shell.py +1 -5
  6. rasa/cli/arguments/train.py +0 -14
  7. rasa/cli/e2e_test.py +1 -1
  8. rasa/cli/evaluate.py +8 -8
  9. rasa/cli/inspect.py +5 -7
  10. rasa/cli/interactive.py +0 -1
  11. rasa/cli/llm_fine_tuning.py +1 -1
  12. rasa/cli/project_templates/calm/config.yml +7 -5
  13. rasa/cli/project_templates/calm/endpoints.yml +2 -15
  14. rasa/cli/project_templates/tutorial/config.yml +5 -8
  15. rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
  16. rasa/cli/project_templates/tutorial/data/patterns.yml +0 -5
  17. rasa/cli/project_templates/tutorial/domain.yml +0 -14
  18. rasa/cli/project_templates/tutorial/endpoints.yml +0 -5
  19. rasa/cli/run.py +1 -1
  20. rasa/cli/scaffold.py +2 -4
  21. rasa/cli/studio/studio.py +8 -18
  22. rasa/cli/studio/upload.py +15 -0
  23. rasa/cli/train.py +0 -3
  24. rasa/cli/utils.py +1 -6
  25. rasa/cli/x.py +8 -8
  26. rasa/constants.py +1 -3
  27. rasa/core/actions/action.py +33 -75
  28. rasa/core/actions/e2e_stub_custom_action_executor.py +1 -5
  29. rasa/core/actions/http_custom_action_executor.py +0 -4
  30. rasa/core/channels/channel.py +0 -20
  31. rasa/core/channels/development_inspector.py +2 -8
  32. rasa/core/channels/inspector/dist/assets/{arc-bc141fb2.js → arc-6852c607.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-be2db283.js → c4Diagram-d0fbc5ce-acc952b2.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-55366915.js → classDiagram-936ed81e-848a7597.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-bb529518.js → classDiagram-v2-c3cb15f1-a73d3e68.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-b0ec81d6.js → createText-62fc7601-e5ee049d.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-6166330c.js → edges-f2ad444c-771e517e.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-5ccc6a8e.js → erDiagram-9d236eb7-aa347178.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-fca3bfe4.js → flowDb-1972c806-651fc57d.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4739080f.js → flowDiagram-7ea5b25a-ca67804f.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-587d82d8.js +1 -0
  42. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-7c1b0e0f.js → flowchart-elk-definition-abe16c3d-2dbc568d.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-772fd050.js → ganttDiagram-9b5ea136-25a65bd8.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-8eae1dc9.js → gitGraphDiagram-99d0ae7c-fdc7378d.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-f55afcdf.js → index-2c4b9a3b-6f1fd606.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{index-e7cef9de.js → index-efdd30c1.js} +68 -68
  47. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-124d4a14.js → infoDiagram-736b4530-cb1a041a.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-7c4fae44.js → journeyDiagram-df861f2b-14609879.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{layout-b9885fb6.js → layout-2490f52b.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{line-7c59abb6.js → line-40186f1f.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{linear-4776f780.js → linear-08814e93.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2332c46c.js → mindmap-definition-beec6740-1a534584.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-8fb39303.js → pieDiagram-dbbf0591-72397b61.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-3c7180a2.js → quadrantDiagram-4d7f4fd6-3bb0b6a3.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-e910bcb8.js → requirementDiagram-6fc4c22a-57334f61.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-ead16c89.js → sankeyDiagram-8f13d901-111e1297.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-29a02a19.js → sequenceDiagram-b655622a-10bcfe62.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-042b3137.js → stateDiagram-59f0c015-acaf7513.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-2178c0f3.js → stateDiagram-v2-2b26beab-3ec2a235.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-23ffa4fc.js → styles-080da4f6-62730289.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-94f59763.js → styles-3dcbcfbf-5284ee76.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-78a6bebc.js → styles-9c745c82-642435e3.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-eae2a6f6.js → svgDrawCommon-4835440b-b250a350.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-5c968d92.js → timeline-definition-5b62e21b-c2b147ed.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-fd3db0d5.js → xychartDiagram-2b33534f-f92cfea9.js} +1 -1
  66. rasa/core/channels/inspector/dist/index.html +1 -1
  67. rasa/core/channels/inspector/src/App.tsx +1 -1
  68. rasa/core/channels/inspector/src/helpers/audiostream.ts +16 -77
  69. rasa/core/channels/socketio.py +2 -7
  70. rasa/core/channels/telegram.py +1 -1
  71. rasa/core/channels/twilio.py +1 -1
  72. rasa/core/channels/voice_ready/audiocodes.py +4 -15
  73. rasa/core/channels/voice_ready/jambonz.py +4 -15
  74. rasa/core/channels/voice_ready/twilio_voice.py +21 -6
  75. rasa/core/channels/voice_ready/utils.py +5 -6
  76. rasa/core/channels/voice_stream/asr/asr_engine.py +1 -19
  77. rasa/core/channels/voice_stream/asr/asr_event.py +0 -5
  78. rasa/core/channels/voice_stream/asr/deepgram.py +15 -28
  79. rasa/core/channels/voice_stream/audio_bytes.py +0 -1
  80. rasa/core/channels/voice_stream/browser_audio.py +9 -32
  81. rasa/core/channels/voice_stream/tts/azure.py +3 -9
  82. rasa/core/channels/voice_stream/tts/cartesia.py +8 -12
  83. rasa/core/channels/voice_stream/tts/tts_engine.py +1 -11
  84. rasa/core/channels/voice_stream/twilio_media_streams.py +19 -28
  85. rasa/core/channels/voice_stream/util.py +4 -4
  86. rasa/core/channels/voice_stream/voice_channel.py +42 -222
  87. rasa/core/featurizers/single_state_featurizer.py +1 -22
  88. rasa/core/featurizers/tracker_featurizers.py +18 -115
  89. rasa/core/information_retrieval/qdrant.py +0 -1
  90. rasa/core/nlg/contextual_response_rephraser.py +25 -44
  91. rasa/core/persistor.py +34 -191
  92. rasa/core/policies/enterprise_search_policy.py +60 -119
  93. rasa/core/policies/flows/flow_executor.py +4 -7
  94. rasa/core/policies/intentless_policy.py +22 -82
  95. rasa/core/policies/ted_policy.py +33 -58
  96. rasa/core/policies/unexpected_intent_policy.py +7 -15
  97. rasa/core/processor.py +5 -32
  98. rasa/core/training/interactive.py +35 -34
  99. rasa/core/utils.py +22 -58
  100. rasa/dialogue_understanding/coexistence/llm_based_router.py +12 -39
  101. rasa/dialogue_understanding/commands/__init__.py +0 -4
  102. rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
  103. rasa/dialogue_understanding/commands/utils.py +0 -5
  104. rasa/dialogue_understanding/generator/constants.py +0 -2
  105. rasa/dialogue_understanding/generator/flow_retrieval.py +4 -49
  106. rasa/dialogue_understanding/generator/llm_based_command_generator.py +23 -37
  107. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +10 -57
  108. rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -19
  109. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +0 -3
  110. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +10 -90
  111. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +0 -53
  112. rasa/dialogue_understanding/processor/command_processor.py +1 -21
  113. rasa/e2e_test/assertions.py +16 -133
  114. rasa/e2e_test/assertions_schema.yml +0 -23
  115. rasa/e2e_test/e2e_test_case.py +6 -85
  116. rasa/e2e_test/e2e_test_runner.py +4 -6
  117. rasa/e2e_test/utils/io.py +1 -3
  118. rasa/engine/loader.py +0 -12
  119. rasa/engine/validation.py +11 -541
  120. rasa/keys +1 -0
  121. rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
  122. rasa/model_training.py +7 -29
  123. rasa/nlu/classifiers/diet_classifier.py +25 -38
  124. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
  125. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  126. rasa/nlu/extractors/crf_entity_extractor.py +50 -93
  127. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +16 -45
  128. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
  129. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  130. rasa/nlu/tokenizers/whitespace_tokenizer.py +14 -3
  131. rasa/server.py +1 -3
  132. rasa/shared/constants.py +0 -61
  133. rasa/shared/core/constants.py +0 -9
  134. rasa/shared/core/domain.py +5 -8
  135. rasa/shared/core/flows/flow.py +0 -5
  136. rasa/shared/core/flows/flows_list.py +1 -5
  137. rasa/shared/core/flows/flows_yaml_schema.json +0 -10
  138. rasa/shared/core/flows/validation.py +0 -96
  139. rasa/shared/core/flows/yaml_flows_io.py +4 -13
  140. rasa/shared/core/slots.py +0 -5
  141. rasa/shared/importers/importer.py +2 -19
  142. rasa/shared/importers/rasa.py +1 -5
  143. rasa/shared/nlu/training_data/features.py +2 -120
  144. rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -18
  145. rasa/shared/providers/_configs/azure_openai_client_config.py +3 -5
  146. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  147. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +0 -1
  148. rasa/shared/providers/_configs/utils.py +0 -16
  149. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +29 -18
  150. rasa/shared/providers/embedding/azure_openai_embedding_client.py +21 -54
  151. rasa/shared/providers/embedding/default_litellm_embedding_client.py +0 -24
  152. rasa/shared/providers/llm/_base_litellm_client.py +31 -63
  153. rasa/shared/providers/llm/azure_openai_llm_client.py +29 -50
  154. rasa/shared/providers/llm/default_litellm_llm_client.py +0 -24
  155. rasa/shared/providers/llm/self_hosted_llm_client.py +29 -17
  156. rasa/shared/providers/mappings.py +0 -19
  157. rasa/shared/utils/common.py +2 -37
  158. rasa/shared/utils/io.py +6 -28
  159. rasa/shared/utils/llm.py +46 -353
  160. rasa/shared/utils/yaml.py +82 -181
  161. rasa/studio/auth.py +5 -3
  162. rasa/studio/config.py +4 -13
  163. rasa/studio/constants.py +0 -1
  164. rasa/studio/data_handler.py +4 -13
  165. rasa/studio/upload.py +80 -175
  166. rasa/telemetry.py +17 -94
  167. rasa/tracing/config.py +1 -3
  168. rasa/tracing/instrumentation/attribute_extractors.py +17 -94
  169. rasa/tracing/instrumentation/instrumentation.py +0 -121
  170. rasa/utils/common.py +0 -5
  171. rasa/utils/endpoints.py +1 -27
  172. rasa/utils/io.py +81 -7
  173. rasa/utils/log_utils.py +2 -9
  174. rasa/utils/tensorflow/model_data.py +193 -2
  175. rasa/validator.py +4 -110
  176. rasa/version.py +1 -1
  177. rasa_pro-3.11.0a2.dist-info/METADATA +576 -0
  178. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/RECORD +181 -213
  179. rasa/core/actions/action_repeat_bot_messages.py +0 -89
  180. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +0 -1
  181. rasa/core/channels/voice_stream/asr/azure.py +0 -129
  182. rasa/core/channels/voice_stream/call_state.py +0 -23
  183. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +0 -60
  184. rasa/dialogue_understanding/commands/user_silence_command.py +0 -59
  185. rasa/dialogue_understanding/patterns/repeat.py +0 -37
  186. rasa/dialogue_understanding/patterns/user_silence.py +0 -37
  187. rasa/model_manager/__init__.py +0 -0
  188. rasa/model_manager/config.py +0 -40
  189. rasa/model_manager/model_api.py +0 -559
  190. rasa/model_manager/runner_service.py +0 -286
  191. rasa/model_manager/socket_bridge.py +0 -146
  192. rasa/model_manager/studio_jwt_auth.py +0 -86
  193. rasa/model_manager/trainer_service.py +0 -325
  194. rasa/model_manager/utils.py +0 -87
  195. rasa/model_manager/warm_rasa_process.py +0 -187
  196. rasa/model_service.py +0 -112
  197. rasa/shared/core/flows/utils.py +0 -39
  198. rasa/shared/providers/_configs/litellm_router_client_config.py +0 -220
  199. rasa/shared/providers/_configs/model_group_config.py +0 -167
  200. rasa/shared/providers/_configs/rasa_llm_client_config.py +0 -73
  201. rasa/shared/providers/_utils.py +0 -79
  202. rasa/shared/providers/embedding/litellm_router_embedding_client.py +0 -135
  203. rasa/shared/providers/llm/litellm_router_llm_client.py +0 -182
  204. rasa/shared/providers/llm/rasa_llm_client.py +0 -112
  205. rasa/shared/providers/router/__init__.py +0 -0
  206. rasa/shared/providers/router/_base_litellm_router_client.py +0 -183
  207. rasa/shared/providers/router/router_client.py +0 -73
  208. rasa/shared/utils/health_check/__init__.py +0 -0
  209. rasa/shared/utils/health_check/embeddings_health_check_mixin.py +0 -31
  210. rasa/shared/utils/health_check/health_check.py +0 -258
  211. rasa/shared/utils/health_check/llm_health_check_mixin.py +0 -31
  212. rasa/utils/sanic_error_handler.py +0 -32
  213. rasa/utils/tensorflow/feature_array.py +0 -366
  214. rasa_pro-3.11.0.dist-info/METADATA +0 -198
  215. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/NOTICE +0 -0
  216. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/WHEEL +0 -0
  217. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/entry_points.txt +0 -0
@@ -1,10 +1,7 @@
1
1
  import audioop
2
- import base64
3
- import json
4
-
5
2
  import structlog
6
3
  import uuid
7
- from typing import Any, Awaitable, Callable, Optional, Tuple
4
+ from typing import Any, Awaitable, Callable, List, Optional
8
5
 
9
6
  from sanic import Blueprint, HTTPResponse, Request, response
10
7
  from sanic import Websocket # type: ignore
@@ -12,19 +9,16 @@ from sanic import Websocket # type: ignore
12
9
 
13
10
  from rasa.core.channels import UserMessage
14
11
  from rasa.core.channels.voice_ready.utils import CallParameters
15
- from rasa.core.channels.voice_stream.call_state import call_state
16
12
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
17
13
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
18
14
  from rasa.core.channels.voice_stream.voice_channel import (
19
- ContinueConversationAction,
20
- EndConversationAction,
21
15
  NewAudioAction,
22
16
  VoiceChannelAction,
23
17
  VoiceInputChannel,
24
18
  VoiceOutputChannel,
25
19
  )
26
20
 
27
- logger = structlog.get_logger()
21
+ structlogger = structlog.get_logger()
28
22
 
29
23
 
30
24
  class BrowserAudioOutputChannel(VoiceOutputChannel):
@@ -37,12 +31,10 @@ class BrowserAudioOutputChannel(VoiceOutputChannel):
37
31
  ) -> bytes:
38
32
  return audioop.ulaw2lin(rasa_audio_bytes, 4)
39
33
 
40
- def channel_bytes_to_message(self, recipient_id: str, channel_bytes: bytes) -> str:
41
- return json.dumps({"audio": base64.b64encode(channel_bytes).decode("utf-8")})
42
-
43
- def create_marker_message(self, recipient_id: str) -> Tuple[str, str]:
44
- message_id = uuid.uuid4().hex
45
- return json.dumps({"marker": message_id}), message_id
34
+ def channel_bytes_to_messages(
35
+ self, recipient_id: str, channel_bytes: bytes
36
+ ) -> List[Any]:
37
+ return [channel_bytes]
46
38
 
47
39
 
48
40
  class BrowserAudioInputChannel(VoiceInputChannel):
@@ -63,23 +55,8 @@ class BrowserAudioInputChannel(VoiceInputChannel):
63
55
  self,
64
56
  message: Any,
65
57
  ) -> VoiceChannelAction:
66
- data = json.loads(message)
67
- if "audio" in data:
68
- channel_bytes = base64.b64decode(data["audio"])
69
- audio_bytes = self.channel_bytes_to_rasa_audio_bytes(channel_bytes)
70
- return NewAudioAction(audio_bytes)
71
- elif "marker" in data:
72
- if data["marker"] == call_state.latest_bot_audio_id:
73
- # Just finished streaming last audio bytes
74
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
75
- if call_state.should_hangup:
76
- logger.debug(
77
- "browser_audio.hangup", marker=call_state.latest_bot_audio_id
78
- )
79
- return EndConversationAction()
80
- else:
81
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
82
- return ContinueConversationAction()
58
+ audio_bytes = self.channel_bytes_to_rasa_audio_bytes(message)
59
+ return NewAudioAction(audio_bytes)
83
60
 
84
61
  def create_output_channel(
85
62
  self, voice_websocket: Websocket, tts_engine: TTSEngine
@@ -94,7 +71,7 @@ class BrowserAudioInputChannel(VoiceInputChannel):
94
71
  self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
95
72
  ) -> Blueprint:
96
73
  """Defines a Sanic bluelogger.debug."""
97
- blueprint = Blueprint("browser_audio", __name__)
74
+ blueprint = Blueprint("socketio_webhook", __name__)
98
75
 
99
76
  @blueprint.route("/", methods=["GET"])
100
77
  async def health(_: Request) -> HTTPResponse:
@@ -4,7 +4,7 @@ from dataclasses import dataclass
4
4
 
5
5
  import aiohttp
6
6
  import structlog
7
- from aiohttp import ClientConnectorError, ClientTimeout
7
+ from aiohttp import ClientConnectorError
8
8
 
9
9
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
10
10
  from rasa.core.channels.voice_stream.tts.tts_engine import (
@@ -12,7 +12,6 @@ from rasa.core.channels.voice_stream.tts.tts_engine import (
12
12
  TTSEngineConfig,
13
13
  TTSError,
14
14
  )
15
- from rasa.shared.constants import AZURE_SPEECH_API_KEY_ENV_VAR
16
15
  from rasa.shared.exceptions import ConnectionException
17
16
 
18
17
 
@@ -26,15 +25,13 @@ class AzureTTSConfig(TTSEngineConfig):
26
25
 
27
26
  class AzureTTS(TTSEngine[AzureTTSConfig]):
28
27
  session: Optional[aiohttp.ClientSession] = None
29
- required_env_vars = (AZURE_SPEECH_API_KEY_ENV_VAR,)
30
28
 
31
29
  def __init__(self, config: Optional[AzureTTSConfig] = None):
32
30
  super().__init__(config)
33
- timeout = ClientTimeout(total=self.config.timeout)
34
31
  # Have to create this class-shared session lazily at run time otherwise
35
32
  # the async event loop doesn't work
36
33
  if self.__class__.session is None or self.__class__.session.closed:
37
- self.__class__.session = aiohttp.ClientSession(timeout=timeout)
34
+ self.__class__.session = aiohttp.ClientSession()
38
35
 
39
36
  async def synthesize(
40
37
  self, text: str, config: Optional[AzureTTSConfig] = None
@@ -63,12 +60,10 @@ class AzureTTS(TTSEngine[AzureTTSConfig]):
63
60
  raise TTSError(f"TTS failed: {response.text()}")
64
61
  except ClientConnectorError as e:
65
62
  raise TTSError(e)
66
- except TimeoutError as e:
67
- raise TTSError(e)
68
63
 
69
64
  @staticmethod
70
65
  def get_request_headers() -> dict[str, str]:
71
- azure_speech_api_key = os.environ[AZURE_SPEECH_API_KEY_ENV_VAR]
66
+ azure_speech_api_key = os.environ["AZURE_SPEECH_API_KEY"]
72
67
  return {
73
68
  "Ocp-Apim-Subscription-Key": azure_speech_api_key,
74
69
  "Content-Type": "application/ssml+xml",
@@ -97,7 +92,6 @@ class AzureTTS(TTSEngine[AzureTTSConfig]):
97
92
  return AzureTTSConfig(
98
93
  language="en-US",
99
94
  voice="en-US-JennyNeural",
100
- timeout=10,
101
95
  speech_region="germanywestcentral",
102
96
  )
103
97
 
@@ -3,19 +3,20 @@ from typing import AsyncIterator, Dict, Optional
3
3
  import os
4
4
  import aiohttp
5
5
  import structlog
6
- from aiohttp import ClientConnectorError, ClientTimeout
6
+ from aiohttp import ClientConnectorError
7
7
 
8
8
  from rasa.core.channels.voice_stream.tts.tts_engine import (
9
9
  TTSEngineConfig,
10
10
  )
11
11
 
12
- from rasa.core.channels.voice_stream.audio_bytes import HERTZ, RasaAudioBytes
12
+ from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
13
13
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine, TTSError
14
- from rasa.shared.constants import CARTESIA_API_KEY_ENV_VAR
15
14
  from rasa.shared.exceptions import ConnectionException
16
15
 
17
16
  structlogger = structlog.get_logger()
18
17
 
18
+ CARTESIA_API_KEY = "CARTESIA_API_KEY"
19
+
19
20
 
20
21
  @dataclass
21
22
  class CartesiaTTSConfig(TTSEngineConfig):
@@ -25,15 +26,13 @@ class CartesiaTTSConfig(TTSEngineConfig):
25
26
 
26
27
  class CartesiaTTS(TTSEngine[CartesiaTTSConfig]):
27
28
  session: Optional[aiohttp.ClientSession] = None
28
- required_env_vars = (CARTESIA_API_KEY_ENV_VAR,)
29
29
 
30
30
  def __init__(self, config: Optional[CartesiaTTSConfig] = None):
31
31
  super().__init__(config)
32
- timeout = ClientTimeout(total=self.config.timeout)
33
32
  # Have to create this class-shared session lazily at run time otherwise
34
33
  # the async event loop doesn't work
35
34
  if self.__class__.session is None or self.__class__.session.closed:
36
- self.__class__.session = aiohttp.ClientSession(timeout=timeout)
35
+ self.__class__.session = aiohttp.ClientSession()
37
36
 
38
37
  @staticmethod
39
38
  def get_tts_endpoint() -> str:
@@ -56,13 +55,13 @@ class CartesiaTTS(TTSEngine[CartesiaTTSConfig]):
56
55
  "output_format": {
57
56
  "container": "raw",
58
57
  "encoding": "pcm_mulaw",
59
- "sample_rate": HERTZ,
58
+ "sample_rate": 8000,
60
59
  },
61
60
  }
62
61
 
63
62
  @staticmethod
64
63
  def get_request_headers(config: CartesiaTTSConfig) -> dict[str, str]:
65
- cartesia_api_key = os.environ[CARTESIA_API_KEY_ENV_VAR]
64
+ cartesia_api_key = os.environ.get(CARTESIA_API_KEY)
66
65
  return {
67
66
  "Cartesia-Version": str(config.version),
68
67
  "Content-Type": "application/json",
@@ -89,15 +88,13 @@ class CartesiaTTS(TTSEngine[CartesiaTTSConfig]):
89
88
  return
90
89
  else:
91
90
  structlogger.error(
92
- "cartesia.synthesize.rest.failed",
91
+ "azure.synthesize.rest.failed",
93
92
  status_code=response.status,
94
93
  msg=response.text(),
95
94
  )
96
95
  raise TTSError(f"TTS failed: {response.text()}")
97
96
  except ClientConnectorError as e:
98
97
  raise TTSError(e)
99
- except TimeoutError as e:
100
- raise TTSError(e)
101
98
 
102
99
  def engine_bytes_to_rasa_audio_bytes(self, chunk: bytes) -> RasaAudioBytes:
103
100
  """Convert the generated tts audio bytes into rasa audio bytes."""
@@ -108,7 +105,6 @@ class CartesiaTTS(TTSEngine[CartesiaTTSConfig]):
108
105
  return CartesiaTTSConfig(
109
106
  language="en",
110
107
  voice="248be419-c632-4f23-adf1-5324ed7dbf1d",
111
- timeout=10,
112
108
  model_id="sonic-english",
113
109
  version="2024-06-10",
114
110
  )
@@ -1,10 +1,9 @@
1
- from typing import AsyncIterator, Dict, Generic, Optional, Tuple, Type, TypeVar
1
+ from typing import AsyncIterator, Dict, Generic, Optional, Type, TypeVar
2
2
  from dataclasses import dataclass
3
3
 
4
4
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
5
5
  from rasa.core.channels.voice_stream.util import MergeableConfig
6
6
  from rasa.shared.exceptions import RasaException
7
- from rasa.shared.utils.common import validate_environment
8
7
 
9
8
 
10
9
  class TTSError(RasaException):
@@ -19,20 +18,11 @@ E = TypeVar("E", bound="TTSEngine")
19
18
  class TTSEngineConfig(MergeableConfig):
20
19
  language: Optional[str] = None
21
20
  voice: Optional[str] = None
22
- timeout: Optional[int] = None
23
21
 
24
22
 
25
23
  class TTSEngine(Generic[T]):
26
- required_env_vars: Tuple[str, ...] = ()
27
- required_packages: Tuple[str, ...] = ()
28
-
29
24
  def __init__(self, config: Optional[T] = None):
30
25
  self.config = self.get_default_config().merge(config)
31
- validate_environment(
32
- self.required_env_vars,
33
- self.required_packages,
34
- f"TTS Engine {self.__class__.__name__}",
35
- )
36
26
 
37
27
  async def close_connection(self) -> None:
38
28
  """Cleanup the connection if necessary."""
@@ -1,9 +1,8 @@
1
1
  import base64
2
2
  import json
3
- import uuid
4
-
5
3
  import structlog
6
- from typing import Any, Awaitable, Callable, Dict, Optional, Text, Tuple
4
+ from typing import Any, Awaitable, Callable, Dict, List, Optional, Text
5
+ import uuid
7
6
 
8
7
  from sanic import Blueprint, HTTPResponse, Request, response
9
8
  from sanic import Websocket # type: ignore
@@ -11,7 +10,6 @@ from sanic import Websocket # type: ignore
11
10
 
12
11
  from rasa.core.channels import UserMessage
13
12
  from rasa.core.channels.voice_ready.utils import CallParameters
14
- from rasa.core.channels.voice_stream.call_state import call_state
15
13
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
16
14
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
17
15
  from rasa.core.channels.voice_stream.voice_channel import (
@@ -23,7 +21,7 @@ from rasa.core.channels.voice_stream.voice_channel import (
23
21
  VoiceOutputChannel,
24
22
  )
25
23
 
26
- logger = structlog.get_logger(__name__)
24
+ structlogger = structlog.get_logger()
27
25
 
28
26
 
29
27
  def map_call_params(data: Dict[Text, Any]) -> CallParameters:
@@ -49,18 +47,10 @@ class TwilioMediaStreamsOutputChannel(VoiceOutputChannel):
49
47
  ) -> bytes:
50
48
  return base64.b64encode(rasa_audio_bytes)
51
49
 
52
- def create_marker_message(self, recipient_id: str) -> Tuple[str, str]:
50
+ def channel_bytes_to_messages(
51
+ self, recipient_id: str, channel_bytes: bytes
52
+ ) -> List[Any]:
53
53
  message_id = uuid.uuid4().hex
54
- mark_message = json.dumps(
55
- {
56
- "event": "mark",
57
- "streamSid": recipient_id,
58
- "mark": {"name": message_id},
59
- }
60
- )
61
- return mark_message, message_id
62
-
63
- def channel_bytes_to_message(self, recipient_id: str, channel_bytes: bytes) -> str:
64
54
  media_message = json.dumps(
65
55
  {
66
56
  "event": "media",
@@ -70,7 +60,15 @@ class TwilioMediaStreamsOutputChannel(VoiceOutputChannel):
70
60
  },
71
61
  }
72
62
  )
73
- return media_message
63
+ mark_message = json.dumps(
64
+ {
65
+ "event": "mark",
66
+ "streamSid": recipient_id,
67
+ "mark": {"name": message_id},
68
+ }
69
+ )
70
+ self.latest_message_id = message_id
71
+ return [media_message, mark_message]
74
72
 
75
73
 
76
74
  class TwilioMediaStreamsInputChannel(VoiceInputChannel):
@@ -105,16 +103,9 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
105
103
  elif data["event"] == "stop":
106
104
  return EndConversationAction()
107
105
  elif data["event"] == "mark":
108
- if data["mark"]["name"] == call_state.latest_bot_audio_id:
109
- # Just finished streaming last audio bytes
110
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
111
- if call_state.should_hangup:
112
- logger.debug(
113
- "twilio_streams.hangup", marker=call_state.latest_bot_audio_id
114
- )
115
- return EndConversationAction()
116
- else:
117
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
106
+ if data["mark"]["name"] == self.hangup_after:
107
+ structlogger.debug("twilio_streams.hangup", marker=self.hangup_after)
108
+ return EndConversationAction()
118
109
  return ContinueConversationAction()
119
110
 
120
111
  def create_output_channel(
@@ -140,7 +131,7 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
140
131
  self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
141
132
  ) -> Blueprint:
142
133
  """Defines a Sanic bluelogger.debug."""
143
- blueprint = Blueprint("twilio_media_streams", __name__)
134
+ blueprint = Blueprint("socketio_webhook", __name__)
144
135
 
145
136
  @blueprint.route("/", methods=["GET"])
146
137
  async def health(_: Request) -> HTTPResponse:
@@ -5,7 +5,7 @@ from typing import Optional, Type, TypeVar
5
5
 
6
6
  import structlog
7
7
 
8
- from rasa.core.channels.voice_stream.audio_bytes import HERTZ, RasaAudioBytes
8
+ from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
9
9
  from rasa.shared.exceptions import RasaException
10
10
 
11
11
  structlogger = structlog.get_logger()
@@ -23,16 +23,16 @@ def read_wav_to_rasa_audio_bytes(file_name: str) -> Optional[RasaAudioBytes]:
23
23
  wave_data = audioop.lin2lin(wave_data, wave_object.getsampwidth(), 1)
24
24
  # 8 bit is unsigned
25
25
  # wave_data = audioop.bias(wave_data, 1, 128)
26
- if wave_object.getframerate() != HERTZ:
26
+ if wave_object.getframerate() != 8000:
27
27
  wave_data, _ = audioop.ratecv(
28
- wave_data, 1, 1, wave_object.getframerate(), HERTZ, None
28
+ wave_data, 1, 1, wave_object.getframerate(), 8000, None
29
29
  )
30
30
  wave_data = audioop.lin2ulaw(wave_data, 1)
31
31
  return RasaAudioBytes(wave_data)
32
32
 
33
33
 
34
34
  def generate_silence(length_in_seconds: float = 1.0) -> RasaAudioBytes:
35
- return RasaAudioBytes(b"\00" * int(length_in_seconds * HERTZ))
35
+ return RasaAudioBytes(b"\00" * int(length_in_seconds * 8000))
36
36
 
37
37
 
38
38
  T = TypeVar("T", bound="MergeableConfig")