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.
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/METADATA +137 -93
- dv_pipecat_ai-0.0.82.dev776.dist-info/RECORD +340 -0
- pipecat/__init__.py +17 -0
- pipecat/adapters/base_llm_adapter.py +36 -1
- pipecat/adapters/schemas/direct_function.py +296 -0
- pipecat/adapters/schemas/function_schema.py +15 -6
- pipecat/adapters/schemas/tools_schema.py +55 -7
- pipecat/adapters/services/anthropic_adapter.py +22 -3
- pipecat/adapters/services/aws_nova_sonic_adapter.py +23 -3
- pipecat/adapters/services/bedrock_adapter.py +22 -3
- pipecat/adapters/services/gemini_adapter.py +16 -3
- pipecat/adapters/services/open_ai_adapter.py +17 -2
- pipecat/adapters/services/open_ai_realtime_adapter.py +23 -3
- pipecat/audio/filters/base_audio_filter.py +30 -6
- pipecat/audio/filters/koala_filter.py +37 -2
- pipecat/audio/filters/krisp_filter.py +59 -6
- pipecat/audio/filters/noisereduce_filter.py +37 -0
- pipecat/audio/interruptions/base_interruption_strategy.py +25 -5
- pipecat/audio/interruptions/min_words_interruption_strategy.py +21 -4
- pipecat/audio/mixers/base_audio_mixer.py +30 -7
- pipecat/audio/mixers/soundfile_mixer.py +53 -6
- pipecat/audio/resamplers/base_audio_resampler.py +17 -9
- pipecat/audio/resamplers/resampy_resampler.py +26 -1
- pipecat/audio/resamplers/soxr_resampler.py +32 -1
- pipecat/audio/resamplers/soxr_stream_resampler.py +101 -0
- pipecat/audio/utils.py +194 -1
- pipecat/audio/vad/silero.py +60 -3
- pipecat/audio/vad/vad_analyzer.py +114 -30
- pipecat/clocks/base_clock.py +19 -0
- pipecat/clocks/system_clock.py +25 -0
- pipecat/extensions/voicemail/__init__.py +0 -0
- pipecat/extensions/voicemail/voicemail_detector.py +707 -0
- pipecat/frames/frames.py +590 -156
- pipecat/metrics/metrics.py +64 -1
- pipecat/observers/base_observer.py +58 -19
- pipecat/observers/loggers/debug_log_observer.py +56 -64
- pipecat/observers/loggers/llm_log_observer.py +8 -1
- pipecat/observers/loggers/transcription_log_observer.py +19 -7
- pipecat/observers/loggers/user_bot_latency_log_observer.py +32 -5
- pipecat/observers/turn_tracking_observer.py +26 -1
- pipecat/pipeline/base_pipeline.py +5 -7
- pipecat/pipeline/base_task.py +52 -9
- pipecat/pipeline/parallel_pipeline.py +121 -177
- pipecat/pipeline/pipeline.py +129 -20
- pipecat/pipeline/runner.py +50 -1
- pipecat/pipeline/sync_parallel_pipeline.py +132 -32
- pipecat/pipeline/task.py +263 -280
- pipecat/pipeline/task_observer.py +85 -34
- pipecat/pipeline/to_be_updated/merge_pipeline.py +32 -2
- pipecat/processors/aggregators/dtmf_aggregator.py +29 -22
- pipecat/processors/aggregators/gated.py +25 -24
- pipecat/processors/aggregators/gated_openai_llm_context.py +22 -2
- pipecat/processors/aggregators/llm_response.py +398 -89
- pipecat/processors/aggregators/openai_llm_context.py +161 -13
- pipecat/processors/aggregators/sentence.py +25 -14
- pipecat/processors/aggregators/user_response.py +28 -3
- pipecat/processors/aggregators/vision_image_frame.py +24 -14
- pipecat/processors/async_generator.py +28 -0
- pipecat/processors/audio/audio_buffer_processor.py +78 -37
- pipecat/processors/consumer_processor.py +25 -6
- pipecat/processors/filters/frame_filter.py +23 -0
- pipecat/processors/filters/function_filter.py +30 -0
- pipecat/processors/filters/identity_filter.py +17 -2
- pipecat/processors/filters/null_filter.py +24 -1
- pipecat/processors/filters/stt_mute_filter.py +56 -21
- pipecat/processors/filters/wake_check_filter.py +46 -3
- pipecat/processors/filters/wake_notifier_filter.py +21 -3
- pipecat/processors/frame_processor.py +488 -131
- pipecat/processors/frameworks/langchain.py +38 -3
- pipecat/processors/frameworks/rtvi.py +719 -34
- pipecat/processors/gstreamer/pipeline_source.py +41 -0
- pipecat/processors/idle_frame_processor.py +26 -3
- pipecat/processors/logger.py +23 -0
- pipecat/processors/metrics/frame_processor_metrics.py +77 -4
- pipecat/processors/metrics/sentry.py +42 -4
- pipecat/processors/producer_processor.py +34 -14
- pipecat/processors/text_transformer.py +22 -10
- pipecat/processors/transcript_processor.py +48 -29
- pipecat/processors/user_idle_processor.py +31 -21
- pipecat/runner/__init__.py +1 -0
- pipecat/runner/daily.py +132 -0
- pipecat/runner/livekit.py +148 -0
- pipecat/runner/run.py +543 -0
- pipecat/runner/types.py +67 -0
- pipecat/runner/utils.py +515 -0
- pipecat/serializers/base_serializer.py +42 -0
- pipecat/serializers/exotel.py +17 -6
- pipecat/serializers/genesys.py +95 -0
- pipecat/serializers/livekit.py +33 -0
- pipecat/serializers/plivo.py +16 -15
- pipecat/serializers/protobuf.py +37 -1
- pipecat/serializers/telnyx.py +18 -17
- pipecat/serializers/twilio.py +32 -16
- pipecat/services/ai_service.py +5 -3
- pipecat/services/anthropic/llm.py +113 -43
- pipecat/services/assemblyai/models.py +63 -5
- pipecat/services/assemblyai/stt.py +64 -11
- pipecat/services/asyncai/__init__.py +0 -0
- pipecat/services/asyncai/tts.py +501 -0
- pipecat/services/aws/llm.py +185 -111
- pipecat/services/aws/stt.py +217 -23
- pipecat/services/aws/tts.py +118 -52
- pipecat/services/aws/utils.py +101 -5
- pipecat/services/aws_nova_sonic/aws.py +82 -64
- pipecat/services/aws_nova_sonic/context.py +15 -6
- pipecat/services/azure/common.py +10 -2
- pipecat/services/azure/image.py +32 -0
- pipecat/services/azure/llm.py +9 -7
- pipecat/services/azure/stt.py +65 -2
- pipecat/services/azure/tts.py +154 -23
- pipecat/services/cartesia/stt.py +125 -8
- pipecat/services/cartesia/tts.py +102 -38
- pipecat/services/cerebras/llm.py +15 -23
- pipecat/services/deepgram/stt.py +19 -11
- pipecat/services/deepgram/tts.py +36 -0
- pipecat/services/deepseek/llm.py +14 -23
- pipecat/services/elevenlabs/tts.py +330 -64
- pipecat/services/fal/image.py +43 -0
- pipecat/services/fal/stt.py +48 -10
- pipecat/services/fireworks/llm.py +14 -21
- pipecat/services/fish/tts.py +109 -9
- pipecat/services/gemini_multimodal_live/__init__.py +1 -0
- pipecat/services/gemini_multimodal_live/events.py +83 -2
- pipecat/services/gemini_multimodal_live/file_api.py +189 -0
- pipecat/services/gemini_multimodal_live/gemini.py +218 -21
- pipecat/services/gladia/config.py +17 -10
- pipecat/services/gladia/stt.py +82 -36
- pipecat/services/google/frames.py +40 -0
- pipecat/services/google/google.py +2 -0
- pipecat/services/google/image.py +39 -2
- pipecat/services/google/llm.py +176 -58
- pipecat/services/google/llm_openai.py +26 -4
- pipecat/services/google/llm_vertex.py +37 -15
- pipecat/services/google/rtvi.py +41 -0
- pipecat/services/google/stt.py +65 -17
- pipecat/services/google/test-google-chirp.py +45 -0
- pipecat/services/google/tts.py +390 -19
- pipecat/services/grok/llm.py +8 -6
- pipecat/services/groq/llm.py +8 -6
- pipecat/services/groq/stt.py +13 -9
- pipecat/services/groq/tts.py +40 -0
- pipecat/services/hamsa/__init__.py +9 -0
- pipecat/services/hamsa/stt.py +241 -0
- pipecat/services/heygen/__init__.py +5 -0
- pipecat/services/heygen/api.py +281 -0
- pipecat/services/heygen/client.py +620 -0
- pipecat/services/heygen/video.py +338 -0
- pipecat/services/image_service.py +5 -3
- pipecat/services/inworld/__init__.py +1 -0
- pipecat/services/inworld/tts.py +592 -0
- pipecat/services/llm_service.py +127 -45
- pipecat/services/lmnt/tts.py +80 -7
- pipecat/services/mcp_service.py +85 -44
- pipecat/services/mem0/memory.py +42 -13
- pipecat/services/minimax/tts.py +74 -15
- pipecat/services/mistral/__init__.py +0 -0
- pipecat/services/mistral/llm.py +185 -0
- pipecat/services/moondream/vision.py +55 -10
- pipecat/services/neuphonic/tts.py +275 -48
- pipecat/services/nim/llm.py +8 -6
- pipecat/services/ollama/llm.py +27 -7
- pipecat/services/openai/base_llm.py +54 -16
- pipecat/services/openai/image.py +30 -0
- pipecat/services/openai/llm.py +7 -5
- pipecat/services/openai/stt.py +13 -9
- pipecat/services/openai/tts.py +42 -10
- pipecat/services/openai_realtime_beta/azure.py +11 -9
- pipecat/services/openai_realtime_beta/context.py +7 -5
- pipecat/services/openai_realtime_beta/events.py +10 -7
- pipecat/services/openai_realtime_beta/openai.py +37 -18
- pipecat/services/openpipe/llm.py +30 -24
- pipecat/services/openrouter/llm.py +9 -7
- pipecat/services/perplexity/llm.py +15 -19
- pipecat/services/piper/tts.py +26 -12
- pipecat/services/playht/tts.py +227 -65
- pipecat/services/qwen/llm.py +8 -6
- pipecat/services/rime/tts.py +128 -17
- pipecat/services/riva/stt.py +160 -22
- pipecat/services/riva/tts.py +67 -2
- pipecat/services/sambanova/llm.py +19 -17
- pipecat/services/sambanova/stt.py +14 -8
- pipecat/services/sarvam/tts.py +60 -13
- pipecat/services/simli/video.py +82 -21
- pipecat/services/soniox/__init__.py +0 -0
- pipecat/services/soniox/stt.py +398 -0
- pipecat/services/speechmatics/stt.py +29 -17
- pipecat/services/stt_service.py +47 -11
- pipecat/services/tavus/video.py +94 -25
- pipecat/services/together/llm.py +8 -6
- pipecat/services/tts_service.py +77 -53
- pipecat/services/ultravox/stt.py +46 -43
- pipecat/services/vision_service.py +5 -3
- pipecat/services/websocket_service.py +12 -11
- pipecat/services/whisper/base_stt.py +58 -12
- pipecat/services/whisper/stt.py +69 -58
- pipecat/services/xtts/tts.py +59 -2
- pipecat/sync/base_notifier.py +19 -0
- pipecat/sync/event_notifier.py +24 -0
- pipecat/tests/utils.py +73 -5
- pipecat/transcriptions/language.py +24 -0
- pipecat/transports/base_input.py +112 -8
- pipecat/transports/base_output.py +235 -13
- pipecat/transports/base_transport.py +119 -0
- pipecat/transports/local/audio.py +76 -0
- pipecat/transports/local/tk.py +84 -0
- pipecat/transports/network/fastapi_websocket.py +174 -15
- pipecat/transports/network/small_webrtc.py +383 -39
- pipecat/transports/network/webrtc_connection.py +214 -8
- pipecat/transports/network/websocket_client.py +171 -1
- pipecat/transports/network/websocket_server.py +147 -9
- pipecat/transports/services/daily.py +792 -70
- pipecat/transports/services/helpers/daily_rest.py +122 -129
- pipecat/transports/services/livekit.py +339 -4
- pipecat/transports/services/tavus.py +273 -38
- pipecat/utils/asyncio/task_manager.py +92 -186
- pipecat/utils/base_object.py +83 -1
- pipecat/utils/network.py +2 -0
- pipecat/utils/string.py +114 -58
- pipecat/utils/text/base_text_aggregator.py +44 -13
- pipecat/utils/text/base_text_filter.py +46 -0
- pipecat/utils/text/markdown_text_filter.py +70 -14
- pipecat/utils/text/pattern_pair_aggregator.py +18 -14
- pipecat/utils/text/simple_text_aggregator.py +43 -2
- pipecat/utils/text/skip_tags_aggregator.py +21 -13
- pipecat/utils/time.py +36 -0
- pipecat/utils/tracing/class_decorators.py +32 -7
- pipecat/utils/tracing/conversation_context_provider.py +12 -2
- pipecat/utils/tracing/service_attributes.py +80 -64
- pipecat/utils/tracing/service_decorators.py +48 -21
- pipecat/utils/tracing/setup.py +13 -7
- pipecat/utils/tracing/turn_context_provider.py +12 -2
- pipecat/utils/tracing/turn_trace_observer.py +27 -0
- pipecat/utils/utils.py +14 -14
- dv_pipecat_ai-0.0.74.dev770.dist-info/RECORD +0 -319
- pipecat/examples/daily_runner.py +0 -64
- pipecat/examples/run.py +0 -265
- pipecat/utils/asyncio/watchdog_async_iterator.py +0 -72
- pipecat/utils/asyncio/watchdog_event.py +0 -42
- pipecat/utils/asyncio/watchdog_priority_queue.py +0 -48
- pipecat/utils/asyncio/watchdog_queue.py +0 -48
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/WHEEL +0 -0
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/licenses/LICENSE +0 -0
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/top_level.txt +0 -0
- /pipecat/{examples → extensions}/__init__.py +0 -0
pipecat/services/mcp_service.py
CHANGED
|
@@ -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(
|
|
131
|
-
|
|
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(
|
|
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(
|
|
171
|
-
|
|
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(
|
|
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(
|
|
209
|
-
|
|
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(
|
|
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,
|
|
320
|
+
tool_name,
|
|
321
|
+
{"description": tool.description, "input_schema": tool.inputSchema},
|
|
281
322
|
)
|
|
282
323
|
|
|
283
324
|
# Register the wrapped function
|
pipecat/services/mem0/memory.py
CHANGED
|
@@ -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
|
|
pipecat/services/minimax/tts.py
CHANGED
|
@@ -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
|
-
|
|
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[
|
|
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"
|
|
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
|