dv-pipecat-ai 0.0.74.dev770__py3-none-any.whl → 0.0.82.dev776__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 dv-pipecat-ai might be problematic. Click here for more details.

Files changed (244) hide show
  1. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/METADATA +137 -93
  2. dv_pipecat_ai-0.0.82.dev776.dist-info/RECORD +340 -0
  3. pipecat/__init__.py +17 -0
  4. pipecat/adapters/base_llm_adapter.py +36 -1
  5. pipecat/adapters/schemas/direct_function.py +296 -0
  6. pipecat/adapters/schemas/function_schema.py +15 -6
  7. pipecat/adapters/schemas/tools_schema.py +55 -7
  8. pipecat/adapters/services/anthropic_adapter.py +22 -3
  9. pipecat/adapters/services/aws_nova_sonic_adapter.py +23 -3
  10. pipecat/adapters/services/bedrock_adapter.py +22 -3
  11. pipecat/adapters/services/gemini_adapter.py +16 -3
  12. pipecat/adapters/services/open_ai_adapter.py +17 -2
  13. pipecat/adapters/services/open_ai_realtime_adapter.py +23 -3
  14. pipecat/audio/filters/base_audio_filter.py +30 -6
  15. pipecat/audio/filters/koala_filter.py +37 -2
  16. pipecat/audio/filters/krisp_filter.py +59 -6
  17. pipecat/audio/filters/noisereduce_filter.py +37 -0
  18. pipecat/audio/interruptions/base_interruption_strategy.py +25 -5
  19. pipecat/audio/interruptions/min_words_interruption_strategy.py +21 -4
  20. pipecat/audio/mixers/base_audio_mixer.py +30 -7
  21. pipecat/audio/mixers/soundfile_mixer.py +53 -6
  22. pipecat/audio/resamplers/base_audio_resampler.py +17 -9
  23. pipecat/audio/resamplers/resampy_resampler.py +26 -1
  24. pipecat/audio/resamplers/soxr_resampler.py +32 -1
  25. pipecat/audio/resamplers/soxr_stream_resampler.py +101 -0
  26. pipecat/audio/utils.py +194 -1
  27. pipecat/audio/vad/silero.py +60 -3
  28. pipecat/audio/vad/vad_analyzer.py +114 -30
  29. pipecat/clocks/base_clock.py +19 -0
  30. pipecat/clocks/system_clock.py +25 -0
  31. pipecat/extensions/voicemail/__init__.py +0 -0
  32. pipecat/extensions/voicemail/voicemail_detector.py +707 -0
  33. pipecat/frames/frames.py +590 -156
  34. pipecat/metrics/metrics.py +64 -1
  35. pipecat/observers/base_observer.py +58 -19
  36. pipecat/observers/loggers/debug_log_observer.py +56 -64
  37. pipecat/observers/loggers/llm_log_observer.py +8 -1
  38. pipecat/observers/loggers/transcription_log_observer.py +19 -7
  39. pipecat/observers/loggers/user_bot_latency_log_observer.py +32 -5
  40. pipecat/observers/turn_tracking_observer.py +26 -1
  41. pipecat/pipeline/base_pipeline.py +5 -7
  42. pipecat/pipeline/base_task.py +52 -9
  43. pipecat/pipeline/parallel_pipeline.py +121 -177
  44. pipecat/pipeline/pipeline.py +129 -20
  45. pipecat/pipeline/runner.py +50 -1
  46. pipecat/pipeline/sync_parallel_pipeline.py +132 -32
  47. pipecat/pipeline/task.py +263 -280
  48. pipecat/pipeline/task_observer.py +85 -34
  49. pipecat/pipeline/to_be_updated/merge_pipeline.py +32 -2
  50. pipecat/processors/aggregators/dtmf_aggregator.py +29 -22
  51. pipecat/processors/aggregators/gated.py +25 -24
  52. pipecat/processors/aggregators/gated_openai_llm_context.py +22 -2
  53. pipecat/processors/aggregators/llm_response.py +398 -89
  54. pipecat/processors/aggregators/openai_llm_context.py +161 -13
  55. pipecat/processors/aggregators/sentence.py +25 -14
  56. pipecat/processors/aggregators/user_response.py +28 -3
  57. pipecat/processors/aggregators/vision_image_frame.py +24 -14
  58. pipecat/processors/async_generator.py +28 -0
  59. pipecat/processors/audio/audio_buffer_processor.py +78 -37
  60. pipecat/processors/consumer_processor.py +25 -6
  61. pipecat/processors/filters/frame_filter.py +23 -0
  62. pipecat/processors/filters/function_filter.py +30 -0
  63. pipecat/processors/filters/identity_filter.py +17 -2
  64. pipecat/processors/filters/null_filter.py +24 -1
  65. pipecat/processors/filters/stt_mute_filter.py +56 -21
  66. pipecat/processors/filters/wake_check_filter.py +46 -3
  67. pipecat/processors/filters/wake_notifier_filter.py +21 -3
  68. pipecat/processors/frame_processor.py +488 -131
  69. pipecat/processors/frameworks/langchain.py +38 -3
  70. pipecat/processors/frameworks/rtvi.py +719 -34
  71. pipecat/processors/gstreamer/pipeline_source.py +41 -0
  72. pipecat/processors/idle_frame_processor.py +26 -3
  73. pipecat/processors/logger.py +23 -0
  74. pipecat/processors/metrics/frame_processor_metrics.py +77 -4
  75. pipecat/processors/metrics/sentry.py +42 -4
  76. pipecat/processors/producer_processor.py +34 -14
  77. pipecat/processors/text_transformer.py +22 -10
  78. pipecat/processors/transcript_processor.py +48 -29
  79. pipecat/processors/user_idle_processor.py +31 -21
  80. pipecat/runner/__init__.py +1 -0
  81. pipecat/runner/daily.py +132 -0
  82. pipecat/runner/livekit.py +148 -0
  83. pipecat/runner/run.py +543 -0
  84. pipecat/runner/types.py +67 -0
  85. pipecat/runner/utils.py +515 -0
  86. pipecat/serializers/base_serializer.py +42 -0
  87. pipecat/serializers/exotel.py +17 -6
  88. pipecat/serializers/genesys.py +95 -0
  89. pipecat/serializers/livekit.py +33 -0
  90. pipecat/serializers/plivo.py +16 -15
  91. pipecat/serializers/protobuf.py +37 -1
  92. pipecat/serializers/telnyx.py +18 -17
  93. pipecat/serializers/twilio.py +32 -16
  94. pipecat/services/ai_service.py +5 -3
  95. pipecat/services/anthropic/llm.py +113 -43
  96. pipecat/services/assemblyai/models.py +63 -5
  97. pipecat/services/assemblyai/stt.py +64 -11
  98. pipecat/services/asyncai/__init__.py +0 -0
  99. pipecat/services/asyncai/tts.py +501 -0
  100. pipecat/services/aws/llm.py +185 -111
  101. pipecat/services/aws/stt.py +217 -23
  102. pipecat/services/aws/tts.py +118 -52
  103. pipecat/services/aws/utils.py +101 -5
  104. pipecat/services/aws_nova_sonic/aws.py +82 -64
  105. pipecat/services/aws_nova_sonic/context.py +15 -6
  106. pipecat/services/azure/common.py +10 -2
  107. pipecat/services/azure/image.py +32 -0
  108. pipecat/services/azure/llm.py +9 -7
  109. pipecat/services/azure/stt.py +65 -2
  110. pipecat/services/azure/tts.py +154 -23
  111. pipecat/services/cartesia/stt.py +125 -8
  112. pipecat/services/cartesia/tts.py +102 -38
  113. pipecat/services/cerebras/llm.py +15 -23
  114. pipecat/services/deepgram/stt.py +19 -11
  115. pipecat/services/deepgram/tts.py +36 -0
  116. pipecat/services/deepseek/llm.py +14 -23
  117. pipecat/services/elevenlabs/tts.py +330 -64
  118. pipecat/services/fal/image.py +43 -0
  119. pipecat/services/fal/stt.py +48 -10
  120. pipecat/services/fireworks/llm.py +14 -21
  121. pipecat/services/fish/tts.py +109 -9
  122. pipecat/services/gemini_multimodal_live/__init__.py +1 -0
  123. pipecat/services/gemini_multimodal_live/events.py +83 -2
  124. pipecat/services/gemini_multimodal_live/file_api.py +189 -0
  125. pipecat/services/gemini_multimodal_live/gemini.py +218 -21
  126. pipecat/services/gladia/config.py +17 -10
  127. pipecat/services/gladia/stt.py +82 -36
  128. pipecat/services/google/frames.py +40 -0
  129. pipecat/services/google/google.py +2 -0
  130. pipecat/services/google/image.py +39 -2
  131. pipecat/services/google/llm.py +176 -58
  132. pipecat/services/google/llm_openai.py +26 -4
  133. pipecat/services/google/llm_vertex.py +37 -15
  134. pipecat/services/google/rtvi.py +41 -0
  135. pipecat/services/google/stt.py +65 -17
  136. pipecat/services/google/test-google-chirp.py +45 -0
  137. pipecat/services/google/tts.py +390 -19
  138. pipecat/services/grok/llm.py +8 -6
  139. pipecat/services/groq/llm.py +8 -6
  140. pipecat/services/groq/stt.py +13 -9
  141. pipecat/services/groq/tts.py +40 -0
  142. pipecat/services/hamsa/__init__.py +9 -0
  143. pipecat/services/hamsa/stt.py +241 -0
  144. pipecat/services/heygen/__init__.py +5 -0
  145. pipecat/services/heygen/api.py +281 -0
  146. pipecat/services/heygen/client.py +620 -0
  147. pipecat/services/heygen/video.py +338 -0
  148. pipecat/services/image_service.py +5 -3
  149. pipecat/services/inworld/__init__.py +1 -0
  150. pipecat/services/inworld/tts.py +592 -0
  151. pipecat/services/llm_service.py +127 -45
  152. pipecat/services/lmnt/tts.py +80 -7
  153. pipecat/services/mcp_service.py +85 -44
  154. pipecat/services/mem0/memory.py +42 -13
  155. pipecat/services/minimax/tts.py +74 -15
  156. pipecat/services/mistral/__init__.py +0 -0
  157. pipecat/services/mistral/llm.py +185 -0
  158. pipecat/services/moondream/vision.py +55 -10
  159. pipecat/services/neuphonic/tts.py +275 -48
  160. pipecat/services/nim/llm.py +8 -6
  161. pipecat/services/ollama/llm.py +27 -7
  162. pipecat/services/openai/base_llm.py +54 -16
  163. pipecat/services/openai/image.py +30 -0
  164. pipecat/services/openai/llm.py +7 -5
  165. pipecat/services/openai/stt.py +13 -9
  166. pipecat/services/openai/tts.py +42 -10
  167. pipecat/services/openai_realtime_beta/azure.py +11 -9
  168. pipecat/services/openai_realtime_beta/context.py +7 -5
  169. pipecat/services/openai_realtime_beta/events.py +10 -7
  170. pipecat/services/openai_realtime_beta/openai.py +37 -18
  171. pipecat/services/openpipe/llm.py +30 -24
  172. pipecat/services/openrouter/llm.py +9 -7
  173. pipecat/services/perplexity/llm.py +15 -19
  174. pipecat/services/piper/tts.py +26 -12
  175. pipecat/services/playht/tts.py +227 -65
  176. pipecat/services/qwen/llm.py +8 -6
  177. pipecat/services/rime/tts.py +128 -17
  178. pipecat/services/riva/stt.py +160 -22
  179. pipecat/services/riva/tts.py +67 -2
  180. pipecat/services/sambanova/llm.py +19 -17
  181. pipecat/services/sambanova/stt.py +14 -8
  182. pipecat/services/sarvam/tts.py +60 -13
  183. pipecat/services/simli/video.py +82 -21
  184. pipecat/services/soniox/__init__.py +0 -0
  185. pipecat/services/soniox/stt.py +398 -0
  186. pipecat/services/speechmatics/stt.py +29 -17
  187. pipecat/services/stt_service.py +47 -11
  188. pipecat/services/tavus/video.py +94 -25
  189. pipecat/services/together/llm.py +8 -6
  190. pipecat/services/tts_service.py +77 -53
  191. pipecat/services/ultravox/stt.py +46 -43
  192. pipecat/services/vision_service.py +5 -3
  193. pipecat/services/websocket_service.py +12 -11
  194. pipecat/services/whisper/base_stt.py +58 -12
  195. pipecat/services/whisper/stt.py +69 -58
  196. pipecat/services/xtts/tts.py +59 -2
  197. pipecat/sync/base_notifier.py +19 -0
  198. pipecat/sync/event_notifier.py +24 -0
  199. pipecat/tests/utils.py +73 -5
  200. pipecat/transcriptions/language.py +24 -0
  201. pipecat/transports/base_input.py +112 -8
  202. pipecat/transports/base_output.py +235 -13
  203. pipecat/transports/base_transport.py +119 -0
  204. pipecat/transports/local/audio.py +76 -0
  205. pipecat/transports/local/tk.py +84 -0
  206. pipecat/transports/network/fastapi_websocket.py +174 -15
  207. pipecat/transports/network/small_webrtc.py +383 -39
  208. pipecat/transports/network/webrtc_connection.py +214 -8
  209. pipecat/transports/network/websocket_client.py +171 -1
  210. pipecat/transports/network/websocket_server.py +147 -9
  211. pipecat/transports/services/daily.py +792 -70
  212. pipecat/transports/services/helpers/daily_rest.py +122 -129
  213. pipecat/transports/services/livekit.py +339 -4
  214. pipecat/transports/services/tavus.py +273 -38
  215. pipecat/utils/asyncio/task_manager.py +92 -186
  216. pipecat/utils/base_object.py +83 -1
  217. pipecat/utils/network.py +2 -0
  218. pipecat/utils/string.py +114 -58
  219. pipecat/utils/text/base_text_aggregator.py +44 -13
  220. pipecat/utils/text/base_text_filter.py +46 -0
  221. pipecat/utils/text/markdown_text_filter.py +70 -14
  222. pipecat/utils/text/pattern_pair_aggregator.py +18 -14
  223. pipecat/utils/text/simple_text_aggregator.py +43 -2
  224. pipecat/utils/text/skip_tags_aggregator.py +21 -13
  225. pipecat/utils/time.py +36 -0
  226. pipecat/utils/tracing/class_decorators.py +32 -7
  227. pipecat/utils/tracing/conversation_context_provider.py +12 -2
  228. pipecat/utils/tracing/service_attributes.py +80 -64
  229. pipecat/utils/tracing/service_decorators.py +48 -21
  230. pipecat/utils/tracing/setup.py +13 -7
  231. pipecat/utils/tracing/turn_context_provider.py +12 -2
  232. pipecat/utils/tracing/turn_trace_observer.py +27 -0
  233. pipecat/utils/utils.py +14 -14
  234. dv_pipecat_ai-0.0.74.dev770.dist-info/RECORD +0 -319
  235. pipecat/examples/daily_runner.py +0 -64
  236. pipecat/examples/run.py +0 -265
  237. pipecat/utils/asyncio/watchdog_async_iterator.py +0 -72
  238. pipecat/utils/asyncio/watchdog_event.py +0 -42
  239. pipecat/utils/asyncio/watchdog_priority_queue.py +0 -48
  240. pipecat/utils/asyncio/watchdog_queue.py +0 -48
  241. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/WHEEL +0 -0
  242. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/licenses/LICENSE +0 -0
  243. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/top_level.txt +0 -0
  244. /pipecat/{examples → extensions}/__init__.py +0 -0
@@ -13,6 +13,7 @@ from loguru import logger
13
13
 
14
14
  from pipecat.adapters.schemas.function_schema import FunctionSchema
15
15
  from pipecat.adapters.schemas.tools_schema import ToolsSchema
16
+ from pipecat.services.llm_service import FunctionCallParams
16
17
  from pipecat.utils.base_object import BaseObject
17
18
 
18
19
  try:
@@ -35,10 +36,6 @@ class MCPClient(BaseObject):
35
36
  to LLMs. Supports both stdio and SSE server connections with automatic tool
36
37
  registration and schema conversion.
37
38
 
38
- Args:
39
- server_params: Server connection parameters (stdio or SSE).
40
- **kwargs: Additional arguments passed to the parent BaseObject.
41
-
42
39
  Raises:
43
40
  TypeError: If server_params is not a supported parameter type.
44
41
  """
@@ -48,9 +45,16 @@ class MCPClient(BaseObject):
48
45
  server_params: Tuple[StdioServerParameters, SseServerParameters, StreamableHttpParameters],
49
46
  **kwargs,
50
47
  ):
48
+ """Initialize the MCP client with server parameters.
49
+
50
+ Args:
51
+ server_params: Server connection parameters (stdio or SSE).
52
+ **kwargs: Additional arguments passed to the parent BaseObject.
53
+ """
51
54
  super().__init__(**kwargs)
52
55
  self._server_params = server_params
53
56
  self._session = ClientSession
57
+ self._needs_alternate_schema = False
54
58
 
55
59
  if isinstance(server_params, StdioServerParameters):
56
60
  self._client = stdio_client
@@ -78,9 +82,48 @@ class MCPClient(BaseObject):
78
82
  Returns:
79
83
  A ToolsSchema containing all successfully registered tools.
80
84
  """
85
+ # Check once if the LLM needs alternate strict schema
86
+ self._needs_alternate_schema = llm and llm.needs_mcp_alternate_schema()
81
87
  tools_schema = await self._register_tools(llm)
82
88
  return tools_schema
83
89
 
90
+ def _get_alternate_schema_for_strict_validation(self, schema: Dict[str, Any]) -> Dict[str, Any]:
91
+ """Get an alternate JSON schema to be compatible with LLMs that have strict validation.
92
+
93
+ Some LLMs have stricter validation and don't allow certain schema properties
94
+ that are valid in standard JSON Schema.
95
+
96
+ Args:
97
+ schema: The JSON schema to get an alternate schema for
98
+
99
+ Returns:
100
+ An alternate schema compatible with strict validation
101
+ """
102
+ if not isinstance(schema, dict):
103
+ return schema
104
+
105
+ alternate_schema = {}
106
+
107
+ for key, value in schema.items():
108
+ # Skip additionalProperties as some LLMs don't like additionalProperties: false
109
+ if key == "additionalProperties":
110
+ continue
111
+
112
+ # Recursively get alternate schema for nested objects
113
+ if isinstance(value, dict):
114
+ alternate_schema[key] = self._get_alternate_schema_for_strict_validation(value)
115
+ elif isinstance(value, list):
116
+ alternate_schema[key] = [
117
+ self._get_alternate_schema_for_strict_validation(item)
118
+ if isinstance(item, dict)
119
+ else item
120
+ for item in value
121
+ ]
122
+ else:
123
+ alternate_schema[key] = value
124
+
125
+ return alternate_schema
126
+
84
127
  def _convert_mcp_schema_to_pipecat(
85
128
  self, tool_name: str, tool_schema: Dict[str, Any]
86
129
  ) -> FunctionSchema:
@@ -98,6 +141,11 @@ class MCPClient(BaseObject):
98
141
  properties = tool_schema["input_schema"].get("properties", {})
99
142
  required = tool_schema["input_schema"].get("required", [])
100
143
 
144
+ # Only get alternate schema for LLMs that need strict schema validation
145
+ if self._needs_alternate_schema:
146
+ logger.debug("Getting alternate schema for strict validation")
147
+ properties = self._get_alternate_schema_for_strict_validation(properties)
148
+
101
149
  schema = FunctionSchema(
102
150
  name=tool_name,
103
151
  description=tool_schema["description"],
@@ -118,27 +166,24 @@ class MCPClient(BaseObject):
118
166
  A ToolsSchema containing all registered tools
119
167
  """
120
168
 
121
- async def mcp_tool_wrapper(
122
- function_name: str,
123
- tool_call_id: str,
124
- arguments: Dict[str, Any],
125
- llm: any,
126
- context: any,
127
- result_callback: any,
128
- ) -> None:
169
+ async def mcp_tool_wrapper(params: FunctionCallParams) -> None:
129
170
  """Wrapper for mcp tool calls to match Pipecat's function call interface."""
130
- logger.debug(f"Executing tool '{function_name}' with call ID: {tool_call_id}")
131
- logger.trace(f"Tool arguments: {json.dumps(arguments, indent=2)}")
171
+ logger.debug(
172
+ f"Executing tool '{params.function_name}' with call ID: {params.tool_call_id}"
173
+ )
174
+ logger.trace(f"Tool arguments: {json.dumps(params.arguments, indent=2)}")
132
175
  try:
133
176
  async with self._client(**self._server_params.model_dump()) as (read, write):
134
177
  async with self._session(read, write) as session:
135
178
  await session.initialize()
136
- await self._call_tool(session, function_name, arguments, result_callback)
179
+ await self._call_tool(
180
+ session, params.function_name, params.arguments, params.result_callback
181
+ )
137
182
  except Exception as e:
138
- error_msg = f"Error calling mcp tool {function_name}: {str(e)}"
183
+ error_msg = f"Error calling mcp tool {params.function_name}: {str(e)}"
139
184
  logger.error(error_msg)
140
185
  logger.exception("Full exception details:")
141
- await result_callback(error_msg)
186
+ await params.result_callback(error_msg)
142
187
 
143
188
  logger.debug(f"SSE server parameters: {self._server_params}")
144
189
  logger.debug("Starting registration of mcp tools")
@@ -158,27 +203,24 @@ class MCPClient(BaseObject):
158
203
  A ToolsSchema containing all registered tools
159
204
  """
160
205
 
161
- async def mcp_tool_wrapper(
162
- function_name: str,
163
- tool_call_id: str,
164
- arguments: Dict[str, Any],
165
- llm: any,
166
- context: any,
167
- result_callback: any,
168
- ) -> None:
206
+ async def mcp_tool_wrapper(params: FunctionCallParams) -> None:
169
207
  """Wrapper for mcp tool calls to match Pipecat's function call interface."""
170
- logger.debug(f"Executing tool '{function_name}' with call ID: {tool_call_id}")
171
- logger.trace(f"Tool arguments: {json.dumps(arguments, indent=2)}")
208
+ logger.debug(
209
+ f"Executing tool '{params.function_name}' with call ID: {params.tool_call_id}"
210
+ )
211
+ logger.trace(f"Tool arguments: {json.dumps(params.arguments, indent=2)}")
172
212
  try:
173
213
  async with self._client(self._server_params) as streams:
174
214
  async with self._session(streams[0], streams[1]) as session:
175
215
  await session.initialize()
176
- await self._call_tool(session, function_name, arguments, result_callback)
216
+ await self._call_tool(
217
+ session, params.function_name, params.arguments, params.result_callback
218
+ )
177
219
  except Exception as e:
178
- error_msg = f"Error calling mcp tool {function_name}: {str(e)}"
220
+ error_msg = f"Error calling mcp tool {params.function_name}: {str(e)}"
179
221
  logger.error(error_msg)
180
222
  logger.exception("Full exception details:")
181
- await result_callback(error_msg)
223
+ await params.result_callback(error_msg)
182
224
 
183
225
  logger.debug("Starting registration of mcp tools")
184
226
 
@@ -190,23 +232,19 @@ class MCPClient(BaseObject):
190
232
 
191
233
  async def _streamable_http_register_tools(self, llm) -> ToolsSchema:
192
234
  """Register all available mcp tools with the LLM service using streamable HTTP.
235
+
193
236
  Args:
194
237
  llm: The Pipecat LLM service to register tools with
195
238
  Returns:
196
239
  A ToolsSchema containing all registered tools
197
240
  """
198
241
 
199
- async def mcp_tool_wrapper(
200
- function_name: str,
201
- tool_call_id: str,
202
- arguments: Dict[str, Any],
203
- llm: any,
204
- context: any,
205
- result_callback: any,
206
- ) -> None:
242
+ async def mcp_tool_wrapper(params: FunctionCallParams) -> None:
207
243
  """Wrapper for mcp tool calls to match Pipecat's function call interface."""
208
- logger.debug(f"Executing tool '{function_name}' with call ID: {tool_call_id}")
209
- logger.trace(f"Tool arguments: {json.dumps(arguments, indent=2)}")
244
+ logger.debug(
245
+ f"Executing tool '{params.function_name}' with call ID: {params.tool_call_id}"
246
+ )
247
+ logger.trace(f"Tool arguments: {json.dumps(params.arguments, indent=2)}")
210
248
  try:
211
249
  async with self._client(**self._server_params.model_dump()) as (
212
250
  read_stream,
@@ -215,12 +253,14 @@ class MCPClient(BaseObject):
215
253
  ):
216
254
  async with self._session(read_stream, write_stream) as session:
217
255
  await session.initialize()
218
- await self._call_tool(session, function_name, arguments, result_callback)
256
+ await self._call_tool(
257
+ session, params.function_name, params.arguments, params.result_callback
258
+ )
219
259
  except Exception as e:
220
- error_msg = f"Error calling mcp tool {function_name}: {str(e)}"
260
+ error_msg = f"Error calling mcp tool {params.function_name}: {str(e)}"
221
261
  logger.error(error_msg)
222
262
  logger.exception("Full exception details:")
223
- await result_callback(error_msg)
263
+ await params.result_callback(error_msg)
224
264
 
225
265
  logger.debug("Starting registration of mcp tools using streamable HTTP")
226
266
 
@@ -277,7 +317,8 @@ class MCPClient(BaseObject):
277
317
  try:
278
318
  # Convert the schema
279
319
  function_schema = self._convert_mcp_schema_to_pipecat(
280
- tool_name, {"description": tool.description, "input_schema": tool.inputSchema}
320
+ tool_name,
321
+ {"description": tool.description, "input_schema": tool.inputSchema},
281
322
  )
282
323
 
283
324
  # Register the wrapped function
@@ -4,6 +4,13 @@
4
4
  # SPDX-License-Identifier: BSD 2-Clause License
5
5
  #
6
6
 
7
+ """Mem0 memory service integration for Pipecat.
8
+
9
+ This module provides a memory service that integrates with Mem0 to store
10
+ and retrieve conversational memories, enhancing LLM context with relevant
11
+ historical information.
12
+ """
13
+
7
14
  from typing import Any, Dict, List, Optional
8
15
 
9
16
  from loguru import logger
@@ -31,14 +38,21 @@ class Mem0MemoryService(FrameProcessor):
31
38
 
32
39
  This service intercepts message frames in the pipeline, stores them in Mem0,
33
40
  and enhances context with relevant memories before passing them downstream.
34
-
35
- Args:
36
- api_key (str): The API key for accessing Mem0's API
37
- user_id (str): The user ID to associate with memories in Mem0
38
- params (InputParams, optional): Configuration parameters for memory retrieval
41
+ Supports both local and cloud-based Mem0 configurations.
39
42
  """
40
43
 
41
44
  class InputParams(BaseModel):
45
+ """Configuration parameters for Mem0 memory service.
46
+
47
+ Parameters:
48
+ search_limit: Maximum number of memories to retrieve per query.
49
+ search_threshold: Minimum similarity threshold for memory retrieval.
50
+ api_version: API version to use for Mem0 client operations.
51
+ system_prompt: Prefix text for memory context messages.
52
+ add_as_system_message: Whether to add memories as system messages.
53
+ position: Position to insert memory messages in context.
54
+ """
55
+
42
56
  search_limit: int = Field(default=10, ge=1)
43
57
  search_threshold: float = Field(default=0.1, ge=0.0, le=1.0)
44
58
  api_version: str = Field(default="v2")
@@ -55,7 +69,22 @@ class Mem0MemoryService(FrameProcessor):
55
69
  agent_id: Optional[str] = None,
56
70
  run_id: Optional[str] = None,
57
71
  params: Optional[InputParams] = None,
72
+ host: Optional[str] = None,
58
73
  ):
74
+ """Initialize the Mem0 memory service.
75
+
76
+ Args:
77
+ api_key: The API key for accessing Mem0's cloud API.
78
+ local_config: Local configuration for Mem0 client (alternative to cloud API).
79
+ user_id: The user ID to associate with memories in Mem0.
80
+ agent_id: The agent ID to associate with memories in Mem0.
81
+ run_id: The run ID to associate with memories in Mem0.
82
+ params: Configuration parameters for memory retrieval and storage.
83
+ host: The host of the Mem0 server.
84
+
85
+ Raises:
86
+ ValueError: If none of user_id, agent_id, or run_id are provided.
87
+ """
59
88
  # Important: Call the parent class __init__ first
60
89
  super().__init__()
61
90
 
@@ -65,7 +94,7 @@ class Mem0MemoryService(FrameProcessor):
65
94
  if local_config:
66
95
  self.memory_client = Memory.from_config(local_config)
67
96
  else:
68
- self.memory_client = MemoryClient(api_key=api_key)
97
+ self.memory_client = MemoryClient(api_key=api_key, host=host)
69
98
  # At least one of user_id, agent_id, or run_id must be provided
70
99
  if not any([user_id, agent_id, run_id]):
71
100
  raise ValueError("At least one of user_id, agent_id, or run_id must be provided")
@@ -86,7 +115,7 @@ class Mem0MemoryService(FrameProcessor):
86
115
  """Store messages in Mem0.
87
116
 
88
117
  Args:
89
- messages: List of message dictionaries to store
118
+ messages: List of message dictionaries to store in memory.
90
119
  """
91
120
  try:
92
121
  logger.debug(f"Storing {len(messages)} messages in Mem0")
@@ -110,10 +139,10 @@ class Mem0MemoryService(FrameProcessor):
110
139
  """Retrieve relevant memories from Mem0.
111
140
 
112
141
  Args:
113
- query: The query to search for relevant memories
142
+ query: The query to search for relevant memories.
114
143
 
115
144
  Returns:
116
- List of relevant memory dictionaries
145
+ List of relevant memory dictionaries matching the query.
117
146
  """
118
147
  try:
119
148
  logger.debug(f"Retrieving memories for query: {query}")
@@ -154,8 +183,8 @@ class Mem0MemoryService(FrameProcessor):
154
183
  """Enhance the LLM context with relevant memories.
155
184
 
156
185
  Args:
157
- context: The OpenAILLMContext to enhance
158
- query: The query to search for relevant memories
186
+ context: The OpenAILLMContext to enhance with memory information.
187
+ query: The query to search for relevant memories.
159
188
  """
160
189
  # Skip if this is the same query we just processed
161
190
  if self.last_query == query:
@@ -184,8 +213,8 @@ class Mem0MemoryService(FrameProcessor):
184
213
  """Process incoming frames, intercept context frames for memory integration.
185
214
 
186
215
  Args:
187
- frame: The incoming frame to process
188
- direction: The direction of frame flow in the pipeline
216
+ frame: The incoming frame to process.
217
+ direction: The direction of frame flow in the pipeline.
189
218
  """
190
219
  await super().process_frame(frame, direction)
191
220
 
@@ -4,6 +4,12 @@
4
4
  # SPDX-License-Identifier: BSD 2-Clause License
5
5
  #
6
6
 
7
+ """MiniMax text-to-speech service implementation.
8
+
9
+ This module provides integration with MiniMax's T2A (Text-to-Audio) API
10
+ for streaming text-to-speech synthesis.
11
+ """
12
+
7
13
  import json
8
14
  from typing import AsyncGenerator, Optional
9
15
 
@@ -25,6 +31,14 @@ from pipecat.utils.tracing.service_decorators import traced_tts
25
31
 
26
32
 
27
33
  def language_to_minimax_language(language: Language) -> Optional[str]:
34
+ """Convert a Language enum to MiniMax language format.
35
+
36
+ Args:
37
+ language: The Language enum value to convert.
38
+
39
+ Returns:
40
+ The corresponding MiniMax language name, or None if not supported.
41
+ """
28
42
  BASE_LANGUAGES = {
29
43
  Language.AR: "Arabic",
30
44
  Language.CS: "Czech",
@@ -71,24 +85,18 @@ def language_to_minimax_language(language: Language) -> Optional[str]:
71
85
  class MiniMaxHttpTTSService(TTSService):
72
86
  """Text-to-speech service using MiniMax's T2A (Text-to-Audio) API.
73
87
 
88
+ Provides streaming text-to-speech synthesis using MiniMax's HTTP API
89
+ with support for various voice settings, emotions, and audio configurations.
90
+ Supports real-time audio streaming with configurable voice parameters.
91
+
74
92
  Platform documentation:
75
93
  https://www.minimax.io/platform/document/T2A%20V2?key=66719005a427f0c8a5701643
76
-
77
- Args:
78
- api_key: MiniMax API key for authentication.
79
- group_id: MiniMax Group ID to identify project.
80
- model: TTS model name (default: "speech-02-turbo"). Options include
81
- "speech-02-hd", "speech-02-turbo", "speech-01-hd", "speech-01-turbo".
82
- voice_id: Voice identifier (default: "Calm_Woman").
83
- aiohttp_session: aiohttp.ClientSession for API communication.
84
- sample_rate: Output audio sample rate in Hz (default: None, set from pipeline).
85
- params: Additional configuration parameters.
86
94
  """
87
95
 
88
96
  class InputParams(BaseModel):
89
97
  """Configuration parameters for MiniMax TTS.
90
98
 
91
- Attributes:
99
+ Parameters:
92
100
  language: Language for TTS generation.
93
101
  speed: Speech speed (range: 0.5 to 2.0).
94
102
  volume: Speech volume (range: 0 to 10).
@@ -101,7 +109,7 @@ class MiniMaxHttpTTSService(TTSService):
101
109
  language: Optional[Language] = Language.EN
102
110
  speed: Optional[float] = 1.0
103
111
  volume: Optional[float] = 1.0
104
- pitch: Optional[float] = 0
112
+ pitch: Optional[int] = 0
105
113
  emotion: Optional[str] = None
106
114
  english_normalization: Optional[bool] = None
107
115
 
@@ -109,6 +117,7 @@ class MiniMaxHttpTTSService(TTSService):
109
117
  self,
110
118
  *,
111
119
  api_key: str,
120
+ base_url: str = "https://api.minimax.io/v1/t2a_v2",
112
121
  group_id: str,
113
122
  model: str = "speech-02-turbo",
114
123
  voice_id: str = "Calm_Woman",
@@ -117,13 +126,29 @@ class MiniMaxHttpTTSService(TTSService):
117
126
  params: Optional[InputParams] = None,
118
127
  **kwargs,
119
128
  ):
129
+ """Initialize the MiniMax TTS service.
130
+
131
+ Args:
132
+ api_key: MiniMax API key for authentication.
133
+ base_url: API base URL, defaults to MiniMax's T2A endpoint.
134
+ Global: https://api.minimax.io/v1/t2a_v2
135
+ Mainland China: https://api.minimaxi.chat/v1/t2a_v2
136
+ group_id: MiniMax Group ID to identify project.
137
+ model: TTS model name. Defaults to "speech-02-turbo". Options include
138
+ "speech-02-hd", "speech-02-turbo", "speech-01-hd", "speech-01-turbo".
139
+ voice_id: Voice identifier. Defaults to "Calm_Woman".
140
+ aiohttp_session: aiohttp.ClientSession for API communication.
141
+ sample_rate: Output audio sample rate in Hz. If None, uses pipeline default.
142
+ params: Additional configuration parameters.
143
+ **kwargs: Additional arguments passed to parent TTSService.
144
+ """
120
145
  super().__init__(sample_rate=sample_rate, **kwargs)
121
146
 
122
147
  params = params or MiniMaxHttpTTSService.InputParams()
123
148
 
124
149
  self._api_key = api_key
125
150
  self._group_id = group_id
126
- self._base_url = f"https://api.minimaxi.chat/v1/t2a_v2?GroupId={group_id}"
151
+ self._base_url = f"{base_url}?GroupId={group_id}"
127
152
  self._session = aiohttp_session
128
153
  self._model_name = model
129
154
  self._voice_id = voice_id
@@ -175,28 +200,62 @@ class MiniMaxHttpTTSService(TTSService):
175
200
  self._settings["english_normalization"] = params.english_normalization
176
201
 
177
202
  def can_generate_metrics(self) -> bool:
203
+ """Check if this service can generate processing metrics.
204
+
205
+ Returns:
206
+ True, as MiniMax service supports metrics generation.
207
+ """
178
208
  return True
179
209
 
180
210
  def language_to_service_language(self, language: Language) -> Optional[str]:
211
+ """Convert a Language enum to MiniMax service language format.
212
+
213
+ Args:
214
+ language: The language to convert.
215
+
216
+ Returns:
217
+ The MiniMax-specific language name, or None if not supported.
218
+ """
181
219
  return language_to_minimax_language(language)
182
220
 
183
221
  def set_model_name(self, model: str):
184
- """Set the TTS model to use"""
222
+ """Set the TTS model to use.
223
+
224
+ Args:
225
+ model: The model name to use for synthesis.
226
+ """
185
227
  self._model_name = model
186
228
 
187
229
  def set_voice(self, voice: str):
188
- """Set the voice to use"""
230
+ """Set the voice to use.
231
+
232
+ Args:
233
+ voice: The voice identifier to use for synthesis.
234
+ """
189
235
  self._voice_id = voice
190
236
  if "voice_setting" in self._settings:
191
237
  self._settings["voice_setting"]["voice_id"] = voice
192
238
 
193
239
  async def start(self, frame: StartFrame):
240
+ """Start the MiniMax TTS service.
241
+
242
+ Args:
243
+ frame: The start frame containing initialization parameters.
244
+ """
194
245
  await super().start(frame)
195
246
  self._settings["audio_setting"]["sample_rate"] = self.sample_rate
196
247
  logger.debug(f"MiniMax TTS initialized with sample rate: {self.sample_rate}")
197
248
 
198
249
  @traced_tts
199
250
  async def run_tts(self, text: str) -> AsyncGenerator[Frame, None]:
251
+ """Generate TTS audio from text using MiniMax's streaming API.
252
+
253
+ Args:
254
+ text: The text to synthesize into speech.
255
+
256
+ Yields:
257
+ Frame: Audio frames containing the synthesized speech.
258
+ """
200
259
  logger.debug(f"{self}: Generating TTS [{text}]")
201
260
 
202
261
  headers = {
File without changes