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
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024–2025, Daily
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
"""Direct function wrapper utilities for LLM function calling.
|
|
8
|
+
|
|
9
|
+
This module provides utilities for wrapping "direct" functions that handle LLM
|
|
10
|
+
function calls. Direct functions have their metadata automatically extracted
|
|
11
|
+
from function signatures and docstrings, allowing them to be used without
|
|
12
|
+
accompanying configurations (as FunctionSchemas or in provider-specific
|
|
13
|
+
formats).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import inspect
|
|
17
|
+
import types
|
|
18
|
+
from typing import (
|
|
19
|
+
TYPE_CHECKING,
|
|
20
|
+
Any,
|
|
21
|
+
Callable,
|
|
22
|
+
Dict,
|
|
23
|
+
List,
|
|
24
|
+
Mapping,
|
|
25
|
+
Protocol,
|
|
26
|
+
Set,
|
|
27
|
+
Tuple,
|
|
28
|
+
Union,
|
|
29
|
+
get_args,
|
|
30
|
+
get_origin,
|
|
31
|
+
get_type_hints,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
import docstring_parser
|
|
35
|
+
|
|
36
|
+
from pipecat.adapters.schemas.function_schema import FunctionSchema
|
|
37
|
+
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
from pipecat.services.llm_service import FunctionCallParams
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DirectFunction(Protocol):
|
|
43
|
+
"""Protocol for a "direct" function that handles LLM function calls.
|
|
44
|
+
|
|
45
|
+
"Direct" functions' metadata is automatically extracted from their function signature and
|
|
46
|
+
docstrings, allowing them to be used without accompanying function configurations (as
|
|
47
|
+
FunctionSchemas or in provider-specific formats).
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
async def __call__(self, params: "FunctionCallParams", **kwargs: Any) -> None:
|
|
51
|
+
"""Execute the direct function.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
params: Function call parameters from the LLM service.
|
|
55
|
+
**kwargs: Additional keyword arguments passed to the function.
|
|
56
|
+
"""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class BaseDirectFunctionWrapper:
|
|
61
|
+
"""Base class for a wrapper around a DirectFunction.
|
|
62
|
+
|
|
63
|
+
Provides functionality to:
|
|
64
|
+
|
|
65
|
+
- extract metadata from the function signature and docstring
|
|
66
|
+
- use that metadata to generate a corresponding FunctionSchema
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, function: Callable):
|
|
70
|
+
"""Initialize the direct function wrapper.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
function: The function to wrap and extract metadata from.
|
|
74
|
+
"""
|
|
75
|
+
self.__class__.validate_function(function)
|
|
76
|
+
self.function = function
|
|
77
|
+
self._initialize_metadata()
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def special_first_param_name(cls) -> str:
|
|
81
|
+
"""Get the name of the special first function parameter.
|
|
82
|
+
|
|
83
|
+
The special first parameter is ignored by metadata extraction as it's
|
|
84
|
+
not relevant to the LLM (e.g., 'params' for FunctionCallParams).
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
The name of the special first parameter.
|
|
88
|
+
"""
|
|
89
|
+
raise NotImplementedError("Subclasses must define the special first parameter name.")
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def validate_function(cls, function: Callable) -> None:
|
|
93
|
+
"""Validate that the function meets direct function requirements.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
function: The function to validate.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
Exception: If function doesn't meet requirements (not async, missing
|
|
100
|
+
parameters, incorrect first parameter name).
|
|
101
|
+
"""
|
|
102
|
+
if not inspect.iscoroutinefunction(function):
|
|
103
|
+
raise Exception(f"Direct function {function.__name__} must be async")
|
|
104
|
+
params = list(inspect.signature(function).parameters.items())
|
|
105
|
+
special_first_param_name = cls.special_first_param_name()
|
|
106
|
+
if len(params) == 0:
|
|
107
|
+
raise Exception(
|
|
108
|
+
f"Direct function {function.__name__} must have at least one parameter ({special_first_param_name})"
|
|
109
|
+
)
|
|
110
|
+
first_param_name = params[0][0]
|
|
111
|
+
if first_param_name != special_first_param_name:
|
|
112
|
+
raise Exception(
|
|
113
|
+
f"Direct function {function.__name__} first parameter must be named '{special_first_param_name}'"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def to_function_schema(self) -> FunctionSchema:
|
|
117
|
+
"""Convert the wrapped function to a FunctionSchema.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
A FunctionSchema instance with extracted metadata.
|
|
121
|
+
"""
|
|
122
|
+
return FunctionSchema(
|
|
123
|
+
name=self.name,
|
|
124
|
+
description=self.description,
|
|
125
|
+
properties=self.properties,
|
|
126
|
+
required=self.required,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def _initialize_metadata(self):
|
|
130
|
+
"""Initialize metadata from function signature and docstring."""
|
|
131
|
+
# Get function name
|
|
132
|
+
self.name = self.function.__name__
|
|
133
|
+
|
|
134
|
+
# Parse docstring for description and parameters
|
|
135
|
+
docstring = docstring_parser.parse(inspect.getdoc(self.function))
|
|
136
|
+
|
|
137
|
+
# Get function description
|
|
138
|
+
self.description = (docstring.description or "").strip()
|
|
139
|
+
|
|
140
|
+
# Get function parameters as JSON schemas, and the list of required parameters
|
|
141
|
+
self.properties, self.required = self._get_parameters_as_jsonschema(
|
|
142
|
+
self.function, docstring.params
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# TODO: maybe to better support things like enums, check if each type is a pydantic type and use its convert-to-jsonschema function
|
|
146
|
+
def _get_parameters_as_jsonschema(
|
|
147
|
+
self, func: Callable, docstring_params: List[docstring_parser.DocstringParam]
|
|
148
|
+
) -> Tuple[Dict[str, Any], List[str]]:
|
|
149
|
+
"""Get function parameters as a dictionary of JSON schemas and a list of required parameters.
|
|
150
|
+
|
|
151
|
+
Ignore the first parameter, as it's expected to be the "special" one.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
func: Function to get parameters from.
|
|
155
|
+
docstring_params: List of parameters extracted from the function's docstring.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
A tuple containing:
|
|
159
|
+
|
|
160
|
+
- A dictionary mapping each function parameter to its JSON schema
|
|
161
|
+
- A list of required parameter names
|
|
162
|
+
"""
|
|
163
|
+
sig = inspect.signature(func)
|
|
164
|
+
hints = get_type_hints(func)
|
|
165
|
+
properties = {}
|
|
166
|
+
required = []
|
|
167
|
+
|
|
168
|
+
for name, param in sig.parameters.items():
|
|
169
|
+
# Ignore 'self' parameter
|
|
170
|
+
if name == "self":
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
# Ignore the first parameter, which is expected to be the "special" one
|
|
174
|
+
# (We have already validated that this is the case in validate_function())
|
|
175
|
+
is_first_param = name == next(iter(sig.parameters))
|
|
176
|
+
if is_first_param:
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
type_hint = hints.get(name)
|
|
180
|
+
|
|
181
|
+
# Convert type hint to JSON schema
|
|
182
|
+
properties[name] = self._typehint_to_jsonschema(type_hint)
|
|
183
|
+
|
|
184
|
+
# Add whether the parameter is required
|
|
185
|
+
# If the parameter has no default value, it's required
|
|
186
|
+
if param.default is inspect.Parameter.empty:
|
|
187
|
+
required.append(name)
|
|
188
|
+
|
|
189
|
+
# Add parameter description from docstring
|
|
190
|
+
for doc_param in docstring_params:
|
|
191
|
+
if doc_param.arg_name == name:
|
|
192
|
+
properties[name]["description"] = doc_param.description or ""
|
|
193
|
+
|
|
194
|
+
return properties, required
|
|
195
|
+
|
|
196
|
+
def _typehint_to_jsonschema(self, type_hint: Any) -> Dict[str, Any]:
|
|
197
|
+
"""Convert a Python type hint to a JSON Schema.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
type_hint: A Python type hint
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
A dictionary representing the JSON Schema
|
|
204
|
+
"""
|
|
205
|
+
if type_hint is None:
|
|
206
|
+
return {}
|
|
207
|
+
|
|
208
|
+
# Handle basic types
|
|
209
|
+
if type_hint is type(None):
|
|
210
|
+
return {"type": "null"}
|
|
211
|
+
if type_hint is str:
|
|
212
|
+
return {"type": "string"}
|
|
213
|
+
elif type_hint is int:
|
|
214
|
+
return {"type": "integer"}
|
|
215
|
+
elif type_hint is float:
|
|
216
|
+
return {"type": "number"}
|
|
217
|
+
elif type_hint is bool:
|
|
218
|
+
return {"type": "boolean"}
|
|
219
|
+
elif type_hint is dict or type_hint is Dict:
|
|
220
|
+
return {"type": "object"}
|
|
221
|
+
elif type_hint is list or type_hint is List:
|
|
222
|
+
return {"type": "array"}
|
|
223
|
+
|
|
224
|
+
# Get origin and arguments for complex types
|
|
225
|
+
origin = get_origin(type_hint)
|
|
226
|
+
args = get_args(type_hint)
|
|
227
|
+
|
|
228
|
+
# Handle Optional/Union types
|
|
229
|
+
if origin is Union or origin is types.UnionType:
|
|
230
|
+
return {"anyOf": [self._typehint_to_jsonschema(arg) for arg in args]}
|
|
231
|
+
|
|
232
|
+
# Handle List, Tuple, Set with specific item types
|
|
233
|
+
if origin in (list, List, tuple, Tuple, set, Set) and args:
|
|
234
|
+
return {"type": "array", "items": self._typehint_to_jsonschema(args[0])}
|
|
235
|
+
|
|
236
|
+
# Handle Dict with specific key/value types
|
|
237
|
+
if origin in (dict, Dict) and len(args) == 2:
|
|
238
|
+
# For JSON Schema, keys must be strings
|
|
239
|
+
return {"type": "object", "additionalProperties": self._typehint_to_jsonschema(args[1])}
|
|
240
|
+
|
|
241
|
+
# Handle TypedDict
|
|
242
|
+
if hasattr(type_hint, "__annotations__"):
|
|
243
|
+
properties = {}
|
|
244
|
+
required = []
|
|
245
|
+
|
|
246
|
+
# NOTE: this does not yet support some fields being required and others not, which could happen when:
|
|
247
|
+
# - the base class is a TypedDict with required fields (total=True or not specified) and the derived class has optional fields (total=False)
|
|
248
|
+
# - Python 3.11+ NotRequired is used
|
|
249
|
+
all_fields_required = getattr(type_hint, "__total__", True)
|
|
250
|
+
|
|
251
|
+
for field_name, field_type in get_type_hints(type_hint).items():
|
|
252
|
+
properties[field_name] = self._typehint_to_jsonschema(field_type)
|
|
253
|
+
if all_fields_required:
|
|
254
|
+
required.append(field_name)
|
|
255
|
+
|
|
256
|
+
schema = {"type": "object", "properties": properties}
|
|
257
|
+
|
|
258
|
+
if required:
|
|
259
|
+
schema["required"] = required
|
|
260
|
+
|
|
261
|
+
return schema
|
|
262
|
+
|
|
263
|
+
# Default to any type if we can't determine the specific schema
|
|
264
|
+
return {}
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class DirectFunctionWrapper(BaseDirectFunctionWrapper):
|
|
268
|
+
"""Wrapper around a DirectFunction for LLM function calling.
|
|
269
|
+
|
|
270
|
+
This class:
|
|
271
|
+
|
|
272
|
+
- Extracts metadata from the function signature and docstring
|
|
273
|
+
- Generates a corresponding FunctionSchema
|
|
274
|
+
- Helps with function invocation
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
@classmethod
|
|
278
|
+
def special_first_param_name(cls) -> str:
|
|
279
|
+
"""Get the special first parameter name for direct functions.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
The string "params" which is expected as the first parameter.
|
|
283
|
+
"""
|
|
284
|
+
return "params"
|
|
285
|
+
|
|
286
|
+
async def invoke(self, args: Mapping[str, Any], params: "FunctionCallParams"):
|
|
287
|
+
"""Invoke the wrapped function with the provided arguments.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
args: Arguments to pass to the function.
|
|
291
|
+
params: Function call parameters from the LLM service.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
The result of the function call.
|
|
295
|
+
"""
|
|
296
|
+
return await self.function(params=params, **args)
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Function schema utilities for AI tool definitions.
|
|
8
|
+
|
|
9
|
+
This module provides standardized function schema representation for defining
|
|
10
|
+
tools and functions used with AI models, ensuring consistent formatting
|
|
11
|
+
across different AI service providers.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
from typing import Any, Dict, List
|
|
8
15
|
|
|
9
16
|
|
|
@@ -13,17 +20,19 @@ class FunctionSchema:
|
|
|
13
20
|
Provides a structured way to define function tools used with AI models like OpenAI.
|
|
14
21
|
This schema defines the function's name, description, parameter properties, and
|
|
15
22
|
required parameters, following specifications required by AI service providers.
|
|
16
|
-
|
|
17
|
-
Args:
|
|
18
|
-
name: Name of the function to be called.
|
|
19
|
-
description: Description of what the function does.
|
|
20
|
-
properties: Dictionary defining parameter types, descriptions, and constraints.
|
|
21
|
-
required: List of property names that are required parameters.
|
|
22
23
|
"""
|
|
23
24
|
|
|
24
25
|
def __init__(
|
|
25
26
|
self, name: str, description: str, properties: Dict[str, Any], required: List[str]
|
|
26
27
|
) -> None:
|
|
28
|
+
"""Initialize the function schema.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
name: Name of the function to be called.
|
|
32
|
+
description: Description of what the function does.
|
|
33
|
+
properties: Dictionary defining parameter types, descriptions, and constraints.
|
|
34
|
+
required: List of property names that are required parameters.
|
|
35
|
+
"""
|
|
27
36
|
self._name = name
|
|
28
37
|
self._description = description
|
|
29
38
|
self._properties = properties
|
|
@@ -4,40 +4,88 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Tools schema definitions for function calling adapters.
|
|
8
|
+
|
|
9
|
+
This module provides schemas for managing both standardized function tools
|
|
10
|
+
and custom adapter-specific tools in the Pipecat framework.
|
|
11
|
+
"""
|
|
12
|
+
|
|
7
13
|
from enum import Enum
|
|
8
14
|
from typing import Any, Dict, List, Optional
|
|
9
15
|
|
|
16
|
+
from pipecat.adapters.schemas.direct_function import DirectFunction, DirectFunctionWrapper
|
|
10
17
|
from pipecat.adapters.schemas.function_schema import FunctionSchema
|
|
11
18
|
|
|
12
19
|
|
|
13
20
|
class AdapterType(Enum):
|
|
21
|
+
"""Supported adapter types for custom tools.
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
GEMINI: Google Gemini adapter - currently the only service supporting custom tools.
|
|
25
|
+
"""
|
|
26
|
+
|
|
14
27
|
GEMINI = "gemini" # that is the only service where we are able to add custom tools for now
|
|
15
28
|
|
|
16
29
|
|
|
17
30
|
class ToolsSchema:
|
|
31
|
+
"""Schema for managing both standard and custom function calling tools.
|
|
32
|
+
|
|
33
|
+
This class provides a unified interface for handling standardized function
|
|
34
|
+
schemas alongside custom tools that may not follow the standard format,
|
|
35
|
+
such as adapter-specific search tools.
|
|
36
|
+
"""
|
|
37
|
+
|
|
18
38
|
def __init__(
|
|
19
39
|
self,
|
|
20
|
-
standard_tools: List[FunctionSchema],
|
|
40
|
+
standard_tools: List[FunctionSchema | DirectFunction],
|
|
21
41
|
custom_tools: Optional[Dict[AdapterType, List[Dict[str, Any]]]] = None,
|
|
22
42
|
) -> None:
|
|
23
|
-
"""
|
|
24
|
-
A schema for tools that includes both standardized function schemas
|
|
25
|
-
and custom tools that do not follow the FunctionSchema format.
|
|
43
|
+
"""Initialize the tools schema.
|
|
26
44
|
|
|
27
|
-
:
|
|
28
|
-
|
|
45
|
+
Args:
|
|
46
|
+
standard_tools: List of tools following the standardized FunctionSchema format.
|
|
47
|
+
custom_tools: Dictionary mapping adapter types to their custom tool definitions.
|
|
48
|
+
These tools may not follow the FunctionSchema format (e.g., search_tool).
|
|
29
49
|
"""
|
|
30
|
-
|
|
50
|
+
|
|
51
|
+
def _map_standard_tools(tools):
|
|
52
|
+
schemas = []
|
|
53
|
+
for tool in tools:
|
|
54
|
+
if isinstance(tool, FunctionSchema):
|
|
55
|
+
schemas.append(tool)
|
|
56
|
+
elif callable(tool):
|
|
57
|
+
wrapper = DirectFunctionWrapper(tool)
|
|
58
|
+
schemas.append(wrapper.to_function_schema())
|
|
59
|
+
else:
|
|
60
|
+
raise TypeError(f"Unsupported tool type: {type(tool)}")
|
|
61
|
+
return schemas
|
|
62
|
+
|
|
63
|
+
self._standard_tools = _map_standard_tools(standard_tools)
|
|
31
64
|
self._custom_tools = custom_tools
|
|
32
65
|
|
|
33
66
|
@property
|
|
34
67
|
def standard_tools(self) -> List[FunctionSchema]:
|
|
68
|
+
"""Get the list of standard function schema tools.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
List of tools following the FunctionSchema format.
|
|
72
|
+
"""
|
|
35
73
|
return self._standard_tools
|
|
36
74
|
|
|
37
75
|
@property
|
|
38
76
|
def custom_tools(self) -> Dict[AdapterType, List[Dict[str, Any]]]:
|
|
77
|
+
"""Get the custom tools dictionary.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dictionary mapping adapter types to their custom tool definitions.
|
|
81
|
+
"""
|
|
39
82
|
return self._custom_tools
|
|
40
83
|
|
|
41
84
|
@custom_tools.setter
|
|
42
85
|
def custom_tools(self, value: Dict[AdapterType, List[Dict[str, Any]]]) -> None:
|
|
86
|
+
"""Set the custom tools dictionary.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
value: Dictionary mapping adapter types to their custom tool definitions.
|
|
90
|
+
"""
|
|
43
91
|
self._custom_tools = value
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Anthropic LLM adapter for Pipecat."""
|
|
8
|
+
|
|
7
9
|
from typing import Any, Dict, List
|
|
8
10
|
|
|
9
11
|
from pipecat.adapters.base_llm_adapter import BaseLLMAdapter
|
|
@@ -12,8 +14,22 @@ from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class AnthropicLLMAdapter(BaseLLMAdapter):
|
|
17
|
+
"""Adapter for converting tool schemas to Anthropic's function-calling format.
|
|
18
|
+
|
|
19
|
+
This adapter handles the conversion of Pipecat's standard function schemas
|
|
20
|
+
to the specific format required by Anthropic's Claude models for function calling.
|
|
21
|
+
"""
|
|
22
|
+
|
|
15
23
|
@staticmethod
|
|
16
24
|
def _to_anthropic_function_format(function: FunctionSchema) -> Dict[str, Any]:
|
|
25
|
+
"""Convert a single function schema to Anthropic's format.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
function: The function schema to convert.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Dictionary containing the function definition in Anthropic's format.
|
|
32
|
+
"""
|
|
17
33
|
return {
|
|
18
34
|
"name": function.name,
|
|
19
35
|
"description": function.description,
|
|
@@ -25,10 +41,13 @@ class AnthropicLLMAdapter(BaseLLMAdapter):
|
|
|
25
41
|
}
|
|
26
42
|
|
|
27
43
|
def to_provider_tools_format(self, tools_schema: ToolsSchema) -> List[Dict[str, Any]]:
|
|
28
|
-
"""
|
|
44
|
+
"""Convert function schemas to Anthropic's function-calling format.
|
|
29
45
|
|
|
30
|
-
:
|
|
31
|
-
|
|
46
|
+
Args:
|
|
47
|
+
tools_schema: The tools schema containing functions to convert.
|
|
32
48
|
|
|
49
|
+
Returns:
|
|
50
|
+
List of function definitions formatted for Anthropic's API.
|
|
51
|
+
"""
|
|
33
52
|
functions_schema = tools_schema.standard_tools
|
|
34
53
|
return [self._to_anthropic_function_format(func) for func in functions_schema]
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
|
+
|
|
7
|
+
"""AWS Nova Sonic LLM adapter for Pipecat."""
|
|
8
|
+
|
|
6
9
|
import json
|
|
7
10
|
from typing import Any, Dict, List
|
|
8
11
|
|
|
@@ -12,8 +15,22 @@ from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class AWSNovaSonicLLMAdapter(BaseLLMAdapter):
|
|
18
|
+
"""Adapter for AWS Nova Sonic language models.
|
|
19
|
+
|
|
20
|
+
Converts Pipecat's standard function schemas into AWS Nova Sonic's
|
|
21
|
+
specific function-calling format, enabling tool use with Nova Sonic models.
|
|
22
|
+
"""
|
|
23
|
+
|
|
15
24
|
@staticmethod
|
|
16
25
|
def _to_aws_nova_sonic_function_format(function: FunctionSchema) -> Dict[str, Any]:
|
|
26
|
+
"""Convert a function schema to AWS Nova Sonic format.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
function: The function schema to convert.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Dictionary in AWS Nova Sonic function format with toolSpec structure.
|
|
33
|
+
"""
|
|
17
34
|
return {
|
|
18
35
|
"toolSpec": {
|
|
19
36
|
"name": function.name,
|
|
@@ -31,10 +48,13 @@ class AWSNovaSonicLLMAdapter(BaseLLMAdapter):
|
|
|
31
48
|
}
|
|
32
49
|
|
|
33
50
|
def to_provider_tools_format(self, tools_schema: ToolsSchema) -> List[Dict[str, Any]]:
|
|
34
|
-
"""
|
|
51
|
+
"""Convert tools schema to AWS Nova Sonic function-calling format.
|
|
35
52
|
|
|
36
|
-
:
|
|
37
|
-
|
|
53
|
+
Args:
|
|
54
|
+
tools_schema: The tools schema containing function definitions to convert.
|
|
38
55
|
|
|
56
|
+
Returns:
|
|
57
|
+
List of dictionaries in AWS Nova Sonic function format.
|
|
58
|
+
"""
|
|
39
59
|
functions_schema = tools_schema.standard_tools
|
|
40
60
|
return [self._to_aws_nova_sonic_function_format(func) for func in functions_schema]
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""AWS Bedrock LLM adapter for Pipecat."""
|
|
8
|
+
|
|
7
9
|
from typing import Any, Dict, List
|
|
8
10
|
|
|
9
11
|
from pipecat.adapters.base_llm_adapter import BaseLLMAdapter
|
|
@@ -12,8 +14,22 @@ from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class AWSBedrockLLMAdapter(BaseLLMAdapter):
|
|
17
|
+
"""Adapter for AWS Bedrock LLM integration with Pipecat.
|
|
18
|
+
|
|
19
|
+
Provides conversion utilities for transforming Pipecat function schemas
|
|
20
|
+
into AWS Bedrock's expected tool format for function calling capabilities.
|
|
21
|
+
"""
|
|
22
|
+
|
|
15
23
|
@staticmethod
|
|
16
24
|
def _to_bedrock_function_format(function: FunctionSchema) -> Dict[str, Any]:
|
|
25
|
+
"""Convert a function schema to Bedrock's tool format.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
function: The function schema to convert.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Dictionary formatted for Bedrock's tool specification.
|
|
32
|
+
"""
|
|
17
33
|
return {
|
|
18
34
|
"toolSpec": {
|
|
19
35
|
"name": function.name,
|
|
@@ -29,10 +45,13 @@ class AWSBedrockLLMAdapter(BaseLLMAdapter):
|
|
|
29
45
|
}
|
|
30
46
|
|
|
31
47
|
def to_provider_tools_format(self, tools_schema: ToolsSchema) -> List[Dict[str, Any]]:
|
|
32
|
-
"""
|
|
48
|
+
"""Convert function schemas to Bedrock's function-calling format.
|
|
33
49
|
|
|
34
|
-
:
|
|
35
|
-
|
|
50
|
+
Args:
|
|
51
|
+
tools_schema: The tools schema containing functions to convert.
|
|
36
52
|
|
|
53
|
+
Returns:
|
|
54
|
+
List of Bedrock formatted function call definitions.
|
|
55
|
+
"""
|
|
37
56
|
functions_schema = tools_schema.standard_tools
|
|
38
57
|
return [self._to_bedrock_function_format(func) for func in functions_schema]
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Gemini LLM adapter for Pipecat."""
|
|
8
|
+
|
|
7
9
|
from typing import Any, Dict, List, Union
|
|
8
10
|
|
|
9
11
|
from pipecat.adapters.base_llm_adapter import BaseLLMAdapter
|
|
@@ -11,12 +13,23 @@ from pipecat.adapters.schemas.tools_schema import AdapterType, ToolsSchema
|
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class GeminiLLMAdapter(BaseLLMAdapter):
|
|
16
|
+
"""LLM adapter for Google's Gemini service.
|
|
17
|
+
|
|
18
|
+
Provides tool schema conversion functionality to transform standard tool
|
|
19
|
+
definitions into Gemini's specific function-calling format for use with
|
|
20
|
+
Gemini LLM models.
|
|
21
|
+
"""
|
|
22
|
+
|
|
14
23
|
def to_provider_tools_format(self, tools_schema: ToolsSchema) -> List[Dict[str, Any]]:
|
|
15
|
-
"""
|
|
24
|
+
"""Convert tool schemas to Gemini's function-calling format.
|
|
16
25
|
|
|
17
|
-
:
|
|
18
|
-
|
|
26
|
+
Args:
|
|
27
|
+
tools_schema: The tools schema containing standard and custom tool definitions.
|
|
19
28
|
|
|
29
|
+
Returns:
|
|
30
|
+
List of tool definitions formatted for Gemini's function-calling API.
|
|
31
|
+
Includes both converted standard tools and any custom Gemini-specific tools.
|
|
32
|
+
"""
|
|
20
33
|
functions_schema = tools_schema.standard_tools
|
|
21
34
|
formatted_standard_tools = [
|
|
22
35
|
{"function_declarations": [func.to_default_dict() for func in functions_schema]}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
|
+
|
|
7
|
+
"""OpenAI LLM adapter for Pipecat."""
|
|
8
|
+
|
|
6
9
|
from typing import List
|
|
7
10
|
|
|
8
11
|
from openai.types.chat import ChatCompletionToolParam
|
|
@@ -12,10 +15,22 @@ from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class OpenAILLMAdapter(BaseLLMAdapter):
|
|
18
|
+
"""Adapter for converting tool schemas to OpenAI's format.
|
|
19
|
+
|
|
20
|
+
Provides conversion utilities for transforming Pipecat's standard tool
|
|
21
|
+
schemas into the format expected by OpenAI's ChatCompletion API for
|
|
22
|
+
function calling capabilities.
|
|
23
|
+
"""
|
|
24
|
+
|
|
15
25
|
def to_provider_tools_format(self, tools_schema: ToolsSchema) -> List[ChatCompletionToolParam]:
|
|
16
|
-
"""
|
|
26
|
+
"""Convert function schemas to OpenAI's function-calling format.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
tools_schema: The Pipecat tools schema to convert.
|
|
17
30
|
|
|
18
|
-
:
|
|
31
|
+
Returns:
|
|
32
|
+
List of OpenAI formatted function call definitions ready for use
|
|
33
|
+
with ChatCompletion API.
|
|
19
34
|
"""
|
|
20
35
|
functions_schema = tools_schema.standard_tools
|
|
21
36
|
return [
|