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
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Simple text aggregator for basic sentence-boundary text processing.
|
|
8
|
+
|
|
9
|
+
This module provides a straightforward text aggregator that accumulates text
|
|
10
|
+
until it finds an end-of-sentence marker, making it suitable for basic TTS
|
|
11
|
+
text processing scenarios.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
from typing import Optional
|
|
8
15
|
|
|
9
16
|
from pipecat.utils.string import match_endofsentence
|
|
@@ -11,19 +18,43 @@ from pipecat.utils.text.base_text_aggregator import BaseTextAggregator
|
|
|
11
18
|
|
|
12
19
|
|
|
13
20
|
class SimpleTextAggregator(BaseTextAggregator):
|
|
14
|
-
"""
|
|
15
|
-
sentence is found.
|
|
21
|
+
"""Simple text aggregator that accumulates text until sentence boundaries.
|
|
16
22
|
|
|
23
|
+
This aggregator provides basic functionality for accumulating text tokens
|
|
24
|
+
and releasing them when an end-of-sentence marker is detected. It's the
|
|
25
|
+
most straightforward implementation of text aggregation for TTS processing.
|
|
17
26
|
"""
|
|
18
27
|
|
|
19
28
|
def __init__(self):
|
|
29
|
+
"""Initialize the simple text aggregator.
|
|
30
|
+
|
|
31
|
+
Creates an empty text buffer ready to begin accumulating text tokens.
|
|
32
|
+
"""
|
|
20
33
|
self._text = ""
|
|
21
34
|
|
|
22
35
|
@property
|
|
23
36
|
def text(self) -> str:
|
|
37
|
+
"""Get the currently aggregated text.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The text that has been accumulated in the buffer.
|
|
41
|
+
"""
|
|
24
42
|
return self._text
|
|
25
43
|
|
|
26
44
|
async def aggregate(self, text: str) -> Optional[str]:
|
|
45
|
+
"""Aggregate text and return completed sentences.
|
|
46
|
+
|
|
47
|
+
Adds the new text to the buffer and checks for end-of-sentence markers.
|
|
48
|
+
When a sentence boundary is found, returns the completed sentence and
|
|
49
|
+
removes it from the buffer.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
text: New text to add to the aggregation buffer.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
A complete sentence if an end-of-sentence marker is found,
|
|
56
|
+
or None if more text is needed to complete a sentence.
|
|
57
|
+
"""
|
|
27
58
|
result: Optional[str] = None
|
|
28
59
|
|
|
29
60
|
self._text += text
|
|
@@ -36,7 +67,17 @@ class SimpleTextAggregator(BaseTextAggregator):
|
|
|
36
67
|
return result
|
|
37
68
|
|
|
38
69
|
async def handle_interruption(self):
|
|
70
|
+
"""Handle interruptions by clearing the text buffer.
|
|
71
|
+
|
|
72
|
+
Called when an interruption occurs in the processing pipeline,
|
|
73
|
+
discarding any partially accumulated text.
|
|
74
|
+
"""
|
|
39
75
|
self._text = ""
|
|
40
76
|
|
|
41
77
|
async def reset(self):
|
|
78
|
+
"""Clear the internally aggregated text.
|
|
79
|
+
|
|
80
|
+
Resets the aggregator to its initial empty state, discarding
|
|
81
|
+
any accumulated text content.
|
|
82
|
+
"""
|
|
42
83
|
self._text = ""
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Skip tags aggregator for preventing sentence boundaries within tagged content.
|
|
8
|
+
|
|
9
|
+
This module provides a text aggregator that prevents end-of-sentence matching
|
|
10
|
+
between specified start/end tag pairs, ensuring that tagged content is processed
|
|
11
|
+
as a unit regardless of internal punctuation.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
from typing import Optional, Sequence
|
|
8
15
|
|
|
9
16
|
from pipecat.utils.string import StartEndTags, match_endofsentence, parse_start_end_tags
|
|
@@ -17,17 +24,18 @@ class SkipTagsAggregator(BaseTextAggregator):
|
|
|
17
24
|
tag. If a start tag is found the aggregator will keep aggregating text
|
|
18
25
|
unconditionally until the corresponding end tag is found. It's particularly
|
|
19
26
|
useful for processing content with custom delimiters that should prevent
|
|
20
|
-
text from being considered for end of sentence matching
|
|
27
|
+
text from being considered for end of sentence matching.
|
|
21
28
|
|
|
22
29
|
The aggregator ensures that tags spanning multiple text chunks are correctly
|
|
23
|
-
identified.
|
|
24
|
-
|
|
30
|
+
identified and that content within tags is never split at sentence boundaries.
|
|
25
31
|
"""
|
|
26
32
|
|
|
27
33
|
def __init__(self, tags: Sequence[StartEndTags]):
|
|
28
|
-
"""Initialize the
|
|
34
|
+
"""Initialize the skip tags aggregator.
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
Args:
|
|
37
|
+
tags: Sequence of StartEndTags objects defining the tag pairs
|
|
38
|
+
that should prevent sentence boundary detection.
|
|
31
39
|
"""
|
|
32
40
|
self._text = ""
|
|
33
41
|
self._tags = tags
|
|
@@ -39,24 +47,24 @@ class SkipTagsAggregator(BaseTextAggregator):
|
|
|
39
47
|
"""Get the currently buffered text.
|
|
40
48
|
|
|
41
49
|
Returns:
|
|
42
|
-
The current text buffer content.
|
|
50
|
+
The current text buffer content that hasn't been processed yet.
|
|
43
51
|
"""
|
|
44
52
|
return self._text
|
|
45
53
|
|
|
46
54
|
async def aggregate(self, text: str) -> Optional[str]:
|
|
47
|
-
"""Aggregate text
|
|
55
|
+
"""Aggregate text while respecting tag boundaries.
|
|
48
56
|
|
|
49
|
-
This method adds the new text to the buffer, processes any complete
|
|
50
|
-
pairs, and returns processed text up to sentence boundaries if
|
|
51
|
-
If there are incomplete patterns (start without matching
|
|
52
|
-
continue buffering text.
|
|
57
|
+
This method adds the new text to the buffer, processes any complete
|
|
58
|
+
pattern pairs, and returns processed text up to sentence boundaries if
|
|
59
|
+
possible. If there are incomplete patterns (start without matching
|
|
60
|
+
end), it will continue buffering text.
|
|
53
61
|
|
|
54
62
|
Args:
|
|
55
63
|
text: New text to add to the buffer.
|
|
56
64
|
|
|
57
65
|
Returns:
|
|
58
|
-
Processed text up to a sentence boundary
|
|
59
|
-
text is needed to
|
|
66
|
+
Processed text up to a sentence boundary (when not within tags),
|
|
67
|
+
or None if more text is needed to complete a sentence or close tags.
|
|
60
68
|
"""
|
|
61
69
|
# Add new text to buffer
|
|
62
70
|
self._text += text
|
pipecat/utils/time.py
CHANGED
|
@@ -4,22 +4,58 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Time utilities for the Pipecat framework.
|
|
8
|
+
|
|
9
|
+
This module provides utility functions for time handling including
|
|
10
|
+
ISO8601 formatting, nanosecond conversions, and human-readable
|
|
11
|
+
time string formatting.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
import datetime
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
def time_now_iso8601() -> str:
|
|
18
|
+
"""Get the current UTC time as an ISO8601 formatted string.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
The current UTC time in ISO8601 format with millisecond precision.
|
|
22
|
+
"""
|
|
11
23
|
return datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="milliseconds")
|
|
12
24
|
|
|
13
25
|
|
|
14
26
|
def seconds_to_nanoseconds(seconds: float) -> int:
|
|
27
|
+
"""Convert seconds to nanoseconds.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
seconds: The number of seconds to convert.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The equivalent number of nanoseconds as an integer.
|
|
34
|
+
"""
|
|
15
35
|
return int(seconds * 1_000_000_000)
|
|
16
36
|
|
|
17
37
|
|
|
18
38
|
def nanoseconds_to_seconds(nanoseconds: int) -> float:
|
|
39
|
+
"""Convert nanoseconds to seconds.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
nanoseconds: The number of nanoseconds to convert.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The equivalent number of seconds as a float.
|
|
46
|
+
"""
|
|
19
47
|
return nanoseconds / 1_000_000_000
|
|
20
48
|
|
|
21
49
|
|
|
22
50
|
def nanoseconds_to_str(nanoseconds: int) -> str:
|
|
51
|
+
"""Convert nanoseconds to a human-readable time string.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
nanoseconds: The number of nanoseconds to convert.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
A formatted time string in "H:MM:SS.microseconds" format.
|
|
58
|
+
"""
|
|
23
59
|
total_seconds = nanoseconds_to_seconds(nanoseconds)
|
|
24
60
|
hours = int(total_seconds // 3600)
|
|
25
61
|
minutes = int((total_seconds % 3600) // 60)
|
|
@@ -33,7 +33,7 @@ C = TypeVar("C", bound=type)
|
|
|
33
33
|
class AttachmentStrategy(enum.Enum):
|
|
34
34
|
"""Controls how spans are attached to the trace hierarchy.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Parameters:
|
|
37
37
|
CHILD: Attached to class span if no parent, otherwise to parent.
|
|
38
38
|
LINK: Attached to class span with link to parent.
|
|
39
39
|
NONE: Always attached to class span regardless of context.
|
|
@@ -71,10 +71,10 @@ class Traceable:
|
|
|
71
71
|
|
|
72
72
|
@property
|
|
73
73
|
def meter(self):
|
|
74
|
-
"""
|
|
74
|
+
"""Get the OpenTelemetry meter instance.
|
|
75
75
|
|
|
76
76
|
Returns:
|
|
77
|
-
|
|
77
|
+
The OpenTelemetry meter instance for this object.
|
|
78
78
|
"""
|
|
79
79
|
return self._meter
|
|
80
80
|
|
|
@@ -83,7 +83,17 @@ class Traceable:
|
|
|
83
83
|
def __traced_context_manager(
|
|
84
84
|
self: Traceable, func: Callable, name: str | None, attachment_strategy: AttachmentStrategy
|
|
85
85
|
):
|
|
86
|
-
"""Internal context manager for the traced decorator.
|
|
86
|
+
"""Internal context manager for the traced decorator.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
self: The Traceable instance.
|
|
90
|
+
func: The function being traced.
|
|
91
|
+
name: Custom span name or None to use function name.
|
|
92
|
+
attachment_strategy: How to attach this span to the trace hierarchy.
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
RuntimeError: If used in a class not inheriting from Traceable.
|
|
96
|
+
"""
|
|
87
97
|
if not isinstance(self, Traceable):
|
|
88
98
|
raise RuntimeError(
|
|
89
99
|
"@traced annotation can only be used in classes inheriting from Traceable"
|
|
@@ -124,7 +134,16 @@ def __traced_context_manager(
|
|
|
124
134
|
|
|
125
135
|
|
|
126
136
|
def __traced_decorator(func, name, attachment_strategy: AttachmentStrategy):
|
|
127
|
-
"""Implementation of the traced decorator.
|
|
137
|
+
"""Implementation of the traced decorator.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
func: The function to trace.
|
|
141
|
+
name: Custom span name.
|
|
142
|
+
attachment_strategy: How to attach this span.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
The wrapped function with tracing capabilities.
|
|
146
|
+
"""
|
|
128
147
|
|
|
129
148
|
@functools.wraps(func)
|
|
130
149
|
async def coroutine_wrapper(self: Traceable, *args, **kwargs):
|
|
@@ -163,7 +182,7 @@ def traced(
|
|
|
163
182
|
name: Optional[str] = None,
|
|
164
183
|
attachment_strategy: AttachmentStrategy = AttachmentStrategy.CHILD,
|
|
165
184
|
) -> Callable:
|
|
166
|
-
"""
|
|
185
|
+
"""Add tracing to an async function in a Traceable class.
|
|
167
186
|
|
|
168
187
|
Args:
|
|
169
188
|
func: The async function to trace.
|
|
@@ -193,7 +212,7 @@ def traced(
|
|
|
193
212
|
|
|
194
213
|
|
|
195
214
|
def traceable(cls: C) -> C:
|
|
196
|
-
"""
|
|
215
|
+
"""Make a class traceable for OpenTelemetry.
|
|
197
216
|
|
|
198
217
|
Creates a new class that inherits from both the original class
|
|
199
218
|
and Traceable, enabling tracing for class methods.
|
|
@@ -210,6 +229,12 @@ def traceable(cls: C) -> C:
|
|
|
210
229
|
@functools.wraps(cls, updated=())
|
|
211
230
|
class TracedClass(cls, Traceable):
|
|
212
231
|
def __init__(self, *args, **kwargs):
|
|
232
|
+
"""Initialize the traced class instance.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
*args: Positional arguments passed to parent classes.
|
|
236
|
+
**kwargs: Keyword arguments passed to parent classes.
|
|
237
|
+
"""
|
|
213
238
|
cls.__init__(self, *args, **kwargs)
|
|
214
239
|
if hasattr(self, "name"):
|
|
215
240
|
Traceable.__init__(self, self.name)
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
"""Conversation context provider for OpenTelemetry tracing in Pipecat.
|
|
8
|
+
|
|
9
|
+
This module provides a singleton context provider that manages the current
|
|
10
|
+
conversation's tracing context, allowing services to create child spans
|
|
11
|
+
that are properly associated with the conversation.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
import uuid
|
|
8
15
|
from typing import TYPE_CHECKING, Optional
|
|
9
16
|
|
|
@@ -32,7 +39,11 @@ class ConversationContextProvider:
|
|
|
32
39
|
|
|
33
40
|
@classmethod
|
|
34
41
|
def get_instance(cls):
|
|
35
|
-
"""Get the singleton instance.
|
|
42
|
+
"""Get the singleton instance.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The singleton ConversationContextProvider instance.
|
|
46
|
+
"""
|
|
36
47
|
if cls._instance is None:
|
|
37
48
|
cls._instance = ConversationContextProvider()
|
|
38
49
|
return cls._instance
|
|
@@ -83,7 +94,6 @@ class ConversationContextProvider:
|
|
|
83
94
|
return str(uuid.uuid4())
|
|
84
95
|
|
|
85
96
|
|
|
86
|
-
# Create a simple helper function to get the current conversation context
|
|
87
97
|
def get_current_conversation_context() -> Optional["Context"]:
|
|
88
98
|
"""Get the OpenTelemetry context for the current conversation.
|
|
89
99
|
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
-
"""Functions for adding attributes to OpenTelemetry spans.
|
|
7
|
+
"""Functions for adding attributes to OpenTelemetry spans.
|
|
8
|
+
|
|
9
|
+
This module provides specialized functions for adding service-specific
|
|
10
|
+
attributes to OpenTelemetry spans, following standard semantic conventions
|
|
11
|
+
where applicable and Pipecat-specific conventions for additional context.
|
|
12
|
+
"""
|
|
8
13
|
|
|
9
14
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
10
15
|
|
|
@@ -26,6 +31,12 @@ def _get_gen_ai_system_from_service_name(service_name: str) -> str:
|
|
|
26
31
|
|
|
27
32
|
Uses standard OTel names where possible, with special case mappings for
|
|
28
33
|
service names that don't follow the pattern.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
service_name: The service class name to extract system name from.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The standardized gen_ai.system value.
|
|
29
40
|
"""
|
|
30
41
|
SPECIAL_CASE_MAPPINGS = {
|
|
31
42
|
# AWS
|
|
@@ -66,16 +77,16 @@ def add_tts_span_attributes(
|
|
|
66
77
|
"""Add TTS-specific attributes to a span.
|
|
67
78
|
|
|
68
79
|
Args:
|
|
69
|
-
span: The span to add attributes to
|
|
70
|
-
service_name: Name of the TTS service (e.g., "cartesia")
|
|
71
|
-
model: Model name/identifier
|
|
72
|
-
voice_id: Voice identifier
|
|
73
|
-
text: The text being synthesized
|
|
74
|
-
settings: Service configuration settings
|
|
75
|
-
character_count: Number of characters in the text
|
|
76
|
-
operation_name: Name of the operation (default: "tts")
|
|
77
|
-
ttfb: Time to first byte in seconds
|
|
78
|
-
**kwargs: Additional attributes to add
|
|
80
|
+
span: The span to add attributes to.
|
|
81
|
+
service_name: Name of the TTS service (e.g., "cartesia").
|
|
82
|
+
model: Model name/identifier.
|
|
83
|
+
voice_id: Voice identifier.
|
|
84
|
+
text: The text being synthesized.
|
|
85
|
+
settings: Service configuration settings.
|
|
86
|
+
character_count: Number of characters in the text.
|
|
87
|
+
operation_name: Name of the operation (default: "tts").
|
|
88
|
+
ttfb: Time to first byte in seconds.
|
|
89
|
+
**kwargs: Additional attributes to add.
|
|
79
90
|
"""
|
|
80
91
|
# Add standard attributes
|
|
81
92
|
span.set_attribute("gen_ai.system", service_name.replace("TTSService", "").lower())
|
|
@@ -114,6 +125,7 @@ def add_stt_span_attributes(
|
|
|
114
125
|
transcript: Optional[str] = None,
|
|
115
126
|
is_final: Optional[bool] = None,
|
|
116
127
|
language: Optional[str] = None,
|
|
128
|
+
user_id: Optional[str] = None,
|
|
117
129
|
settings: Optional[Dict[str, Any]] = None,
|
|
118
130
|
vad_enabled: bool = False,
|
|
119
131
|
ttfb: Optional[float] = None,
|
|
@@ -122,17 +134,18 @@ def add_stt_span_attributes(
|
|
|
122
134
|
"""Add STT-specific attributes to a span.
|
|
123
135
|
|
|
124
136
|
Args:
|
|
125
|
-
span: The span to add attributes to
|
|
126
|
-
service_name: Name of the STT service (e.g., "deepgram")
|
|
127
|
-
model: Model name/identifier
|
|
128
|
-
operation_name: Name of the operation (default: "stt")
|
|
129
|
-
transcript: The transcribed text
|
|
130
|
-
is_final: Whether this is a final transcript
|
|
131
|
-
language: Detected or configured language
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
span: The span to add attributes to.
|
|
138
|
+
service_name: Name of the STT service (e.g., "deepgram").
|
|
139
|
+
model: Model name/identifier.
|
|
140
|
+
operation_name: Name of the operation (default: "stt").
|
|
141
|
+
transcript: The transcribed text.
|
|
142
|
+
is_final: Whether this is a final transcript.
|
|
143
|
+
language: Detected or configured language.
|
|
144
|
+
user_id: User ID associated with the audio being transcribed.
|
|
145
|
+
settings: Service configuration settings.
|
|
146
|
+
vad_enabled: Whether voice activity detection is enabled.
|
|
147
|
+
ttfb: Time to first byte in seconds.
|
|
148
|
+
**kwargs: Additional attributes to add.
|
|
136
149
|
"""
|
|
137
150
|
# Add standard attributes
|
|
138
151
|
span.set_attribute("gen_ai.system", service_name.replace("STTService", "").lower())
|
|
@@ -150,6 +163,9 @@ def add_stt_span_attributes(
|
|
|
150
163
|
if language:
|
|
151
164
|
span.set_attribute("language", language)
|
|
152
165
|
|
|
166
|
+
if user_id:
|
|
167
|
+
span.set_attribute("user_id", user_id)
|
|
168
|
+
|
|
153
169
|
if ttfb is not None:
|
|
154
170
|
span.set_attribute("metrics.ttfb", ttfb)
|
|
155
171
|
|
|
@@ -184,20 +200,20 @@ def add_llm_span_attributes(
|
|
|
184
200
|
"""Add LLM-specific attributes to a span.
|
|
185
201
|
|
|
186
202
|
Args:
|
|
187
|
-
span: The span to add attributes to
|
|
188
|
-
service_name: Name of the LLM service (e.g., "openai")
|
|
189
|
-
model: Model name/identifier
|
|
190
|
-
stream: Whether streaming is enabled
|
|
191
|
-
messages: JSON-serialized messages
|
|
192
|
-
output: Aggregated output text from the LLM
|
|
193
|
-
tools: JSON-serialized tools configuration
|
|
194
|
-
tool_count: Number of tools available
|
|
195
|
-
tool_choice: Tool selection configuration
|
|
196
|
-
system: System message
|
|
197
|
-
parameters: Service parameters
|
|
198
|
-
extra_parameters: Additional parameters
|
|
199
|
-
ttfb: Time to first byte in seconds
|
|
200
|
-
**kwargs: Additional attributes to add
|
|
203
|
+
span: The span to add attributes to.
|
|
204
|
+
service_name: Name of the LLM service (e.g., "openai").
|
|
205
|
+
model: Model name/identifier.
|
|
206
|
+
stream: Whether streaming is enabled.
|
|
207
|
+
messages: JSON-serialized messages.
|
|
208
|
+
output: Aggregated output text from the LLM.
|
|
209
|
+
tools: JSON-serialized tools configuration.
|
|
210
|
+
tool_count: Number of tools available.
|
|
211
|
+
tool_choice: Tool selection configuration.
|
|
212
|
+
system: System message.
|
|
213
|
+
parameters: Service parameters.
|
|
214
|
+
extra_parameters: Additional parameters.
|
|
215
|
+
ttfb: Time to first byte in seconds.
|
|
216
|
+
**kwargs: Additional attributes to add.
|
|
201
217
|
"""
|
|
202
218
|
# Add standard attributes
|
|
203
219
|
span.set_attribute("gen_ai.system", _get_gen_ai_system_from_service_name(service_name))
|
|
@@ -278,21 +294,21 @@ def add_gemini_live_span_attributes(
|
|
|
278
294
|
"""Add Gemini Live specific attributes to a span.
|
|
279
295
|
|
|
280
296
|
Args:
|
|
281
|
-
span: The span to add attributes to
|
|
282
|
-
service_name: Name of the service
|
|
283
|
-
model: Model name/identifier
|
|
284
|
-
operation_name: Name of the operation (setup, model_turn, tool_call, etc.)
|
|
285
|
-
voice_id: Voice identifier used for output
|
|
286
|
-
language: Language code for the session
|
|
287
|
-
modalities: Supported modalities (e.g., "AUDIO", "TEXT")
|
|
288
|
-
settings: Service configuration settings
|
|
289
|
-
tools: Available tools/functions list
|
|
290
|
-
tools_serialized: JSON-serialized tools for detailed inspection
|
|
291
|
-
transcript: Transcription text
|
|
292
|
-
is_input: Whether transcript is input (True) or output (False)
|
|
293
|
-
text_output: Text output from model
|
|
294
|
-
audio_data_size: Size of audio data in bytes
|
|
295
|
-
**kwargs: Additional attributes to add
|
|
297
|
+
span: The span to add attributes to.
|
|
298
|
+
service_name: Name of the service.
|
|
299
|
+
model: Model name/identifier.
|
|
300
|
+
operation_name: Name of the operation (setup, model_turn, tool_call, etc.).
|
|
301
|
+
voice_id: Voice identifier used for output.
|
|
302
|
+
language: Language code for the session.
|
|
303
|
+
modalities: Supported modalities (e.g., "AUDIO", "TEXT").
|
|
304
|
+
settings: Service configuration settings.
|
|
305
|
+
tools: Available tools/functions list.
|
|
306
|
+
tools_serialized: JSON-serialized tools for detailed inspection.
|
|
307
|
+
transcript: Transcription text.
|
|
308
|
+
is_input: Whether transcript is input (True) or output (False).
|
|
309
|
+
text_output: Text output from model.
|
|
310
|
+
audio_data_size: Size of audio data in bytes.
|
|
311
|
+
**kwargs: Additional attributes to add.
|
|
296
312
|
"""
|
|
297
313
|
# Add standard attributes
|
|
298
314
|
span.set_attribute("gen_ai.system", "gcp.gemini")
|
|
@@ -381,19 +397,19 @@ def add_openai_realtime_span_attributes(
|
|
|
381
397
|
"""Add OpenAI Realtime specific attributes to a span.
|
|
382
398
|
|
|
383
399
|
Args:
|
|
384
|
-
span: The span to add attributes to
|
|
385
|
-
service_name: Name of the service
|
|
386
|
-
model: Model name/identifier
|
|
387
|
-
operation_name: Name of the operation (setup, transcription, response, etc.)
|
|
388
|
-
session_properties: Session configuration properties
|
|
389
|
-
transcript: Transcription text
|
|
390
|
-
is_input: Whether transcript is input (True) or output (False)
|
|
391
|
-
context_messages: JSON-serialized context messages
|
|
392
|
-
function_calls: Function calls being made
|
|
393
|
-
tools: Available tools/functions list
|
|
394
|
-
tools_serialized: JSON-serialized tools for detailed inspection
|
|
395
|
-
audio_data_size: Size of audio data in bytes
|
|
396
|
-
**kwargs: Additional attributes to add
|
|
400
|
+
span: The span to add attributes to.
|
|
401
|
+
service_name: Name of the service.
|
|
402
|
+
model: Model name/identifier.
|
|
403
|
+
operation_name: Name of the operation (setup, transcription, response, etc.).
|
|
404
|
+
session_properties: Session configuration properties.
|
|
405
|
+
transcript: Transcription text.
|
|
406
|
+
is_input: Whether transcript is input (True) or output (False).
|
|
407
|
+
context_messages: JSON-serialized context messages.
|
|
408
|
+
function_calls: Function calls being made.
|
|
409
|
+
tools: Available tools/functions list.
|
|
410
|
+
tools_serialized: JSON-serialized tools for detailed inspection.
|
|
411
|
+
audio_data_size: Size of audio data in bytes.
|
|
412
|
+
**kwargs: Additional attributes to add.
|
|
397
413
|
"""
|
|
398
414
|
# Add standard attributes
|
|
399
415
|
span.set_attribute("gen_ai.system", "openai")
|