dv-pipecat-ai 0.0.74.dev770__py3-none-any.whl → 0.0.82.dev776__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dv-pipecat-ai might be problematic. Click here for more details.

Files changed (244) hide show
  1. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/METADATA +137 -93
  2. dv_pipecat_ai-0.0.82.dev776.dist-info/RECORD +340 -0
  3. pipecat/__init__.py +17 -0
  4. pipecat/adapters/base_llm_adapter.py +36 -1
  5. pipecat/adapters/schemas/direct_function.py +296 -0
  6. pipecat/adapters/schemas/function_schema.py +15 -6
  7. pipecat/adapters/schemas/tools_schema.py +55 -7
  8. pipecat/adapters/services/anthropic_adapter.py +22 -3
  9. pipecat/adapters/services/aws_nova_sonic_adapter.py +23 -3
  10. pipecat/adapters/services/bedrock_adapter.py +22 -3
  11. pipecat/adapters/services/gemini_adapter.py +16 -3
  12. pipecat/adapters/services/open_ai_adapter.py +17 -2
  13. pipecat/adapters/services/open_ai_realtime_adapter.py +23 -3
  14. pipecat/audio/filters/base_audio_filter.py +30 -6
  15. pipecat/audio/filters/koala_filter.py +37 -2
  16. pipecat/audio/filters/krisp_filter.py +59 -6
  17. pipecat/audio/filters/noisereduce_filter.py +37 -0
  18. pipecat/audio/interruptions/base_interruption_strategy.py +25 -5
  19. pipecat/audio/interruptions/min_words_interruption_strategy.py +21 -4
  20. pipecat/audio/mixers/base_audio_mixer.py +30 -7
  21. pipecat/audio/mixers/soundfile_mixer.py +53 -6
  22. pipecat/audio/resamplers/base_audio_resampler.py +17 -9
  23. pipecat/audio/resamplers/resampy_resampler.py +26 -1
  24. pipecat/audio/resamplers/soxr_resampler.py +32 -1
  25. pipecat/audio/resamplers/soxr_stream_resampler.py +101 -0
  26. pipecat/audio/utils.py +194 -1
  27. pipecat/audio/vad/silero.py +60 -3
  28. pipecat/audio/vad/vad_analyzer.py +114 -30
  29. pipecat/clocks/base_clock.py +19 -0
  30. pipecat/clocks/system_clock.py +25 -0
  31. pipecat/extensions/voicemail/__init__.py +0 -0
  32. pipecat/extensions/voicemail/voicemail_detector.py +707 -0
  33. pipecat/frames/frames.py +590 -156
  34. pipecat/metrics/metrics.py +64 -1
  35. pipecat/observers/base_observer.py +58 -19
  36. pipecat/observers/loggers/debug_log_observer.py +56 -64
  37. pipecat/observers/loggers/llm_log_observer.py +8 -1
  38. pipecat/observers/loggers/transcription_log_observer.py +19 -7
  39. pipecat/observers/loggers/user_bot_latency_log_observer.py +32 -5
  40. pipecat/observers/turn_tracking_observer.py +26 -1
  41. pipecat/pipeline/base_pipeline.py +5 -7
  42. pipecat/pipeline/base_task.py +52 -9
  43. pipecat/pipeline/parallel_pipeline.py +121 -177
  44. pipecat/pipeline/pipeline.py +129 -20
  45. pipecat/pipeline/runner.py +50 -1
  46. pipecat/pipeline/sync_parallel_pipeline.py +132 -32
  47. pipecat/pipeline/task.py +263 -280
  48. pipecat/pipeline/task_observer.py +85 -34
  49. pipecat/pipeline/to_be_updated/merge_pipeline.py +32 -2
  50. pipecat/processors/aggregators/dtmf_aggregator.py +29 -22
  51. pipecat/processors/aggregators/gated.py +25 -24
  52. pipecat/processors/aggregators/gated_openai_llm_context.py +22 -2
  53. pipecat/processors/aggregators/llm_response.py +398 -89
  54. pipecat/processors/aggregators/openai_llm_context.py +161 -13
  55. pipecat/processors/aggregators/sentence.py +25 -14
  56. pipecat/processors/aggregators/user_response.py +28 -3
  57. pipecat/processors/aggregators/vision_image_frame.py +24 -14
  58. pipecat/processors/async_generator.py +28 -0
  59. pipecat/processors/audio/audio_buffer_processor.py +78 -37
  60. pipecat/processors/consumer_processor.py +25 -6
  61. pipecat/processors/filters/frame_filter.py +23 -0
  62. pipecat/processors/filters/function_filter.py +30 -0
  63. pipecat/processors/filters/identity_filter.py +17 -2
  64. pipecat/processors/filters/null_filter.py +24 -1
  65. pipecat/processors/filters/stt_mute_filter.py +56 -21
  66. pipecat/processors/filters/wake_check_filter.py +46 -3
  67. pipecat/processors/filters/wake_notifier_filter.py +21 -3
  68. pipecat/processors/frame_processor.py +488 -131
  69. pipecat/processors/frameworks/langchain.py +38 -3
  70. pipecat/processors/frameworks/rtvi.py +719 -34
  71. pipecat/processors/gstreamer/pipeline_source.py +41 -0
  72. pipecat/processors/idle_frame_processor.py +26 -3
  73. pipecat/processors/logger.py +23 -0
  74. pipecat/processors/metrics/frame_processor_metrics.py +77 -4
  75. pipecat/processors/metrics/sentry.py +42 -4
  76. pipecat/processors/producer_processor.py +34 -14
  77. pipecat/processors/text_transformer.py +22 -10
  78. pipecat/processors/transcript_processor.py +48 -29
  79. pipecat/processors/user_idle_processor.py +31 -21
  80. pipecat/runner/__init__.py +1 -0
  81. pipecat/runner/daily.py +132 -0
  82. pipecat/runner/livekit.py +148 -0
  83. pipecat/runner/run.py +543 -0
  84. pipecat/runner/types.py +67 -0
  85. pipecat/runner/utils.py +515 -0
  86. pipecat/serializers/base_serializer.py +42 -0
  87. pipecat/serializers/exotel.py +17 -6
  88. pipecat/serializers/genesys.py +95 -0
  89. pipecat/serializers/livekit.py +33 -0
  90. pipecat/serializers/plivo.py +16 -15
  91. pipecat/serializers/protobuf.py +37 -1
  92. pipecat/serializers/telnyx.py +18 -17
  93. pipecat/serializers/twilio.py +32 -16
  94. pipecat/services/ai_service.py +5 -3
  95. pipecat/services/anthropic/llm.py +113 -43
  96. pipecat/services/assemblyai/models.py +63 -5
  97. pipecat/services/assemblyai/stt.py +64 -11
  98. pipecat/services/asyncai/__init__.py +0 -0
  99. pipecat/services/asyncai/tts.py +501 -0
  100. pipecat/services/aws/llm.py +185 -111
  101. pipecat/services/aws/stt.py +217 -23
  102. pipecat/services/aws/tts.py +118 -52
  103. pipecat/services/aws/utils.py +101 -5
  104. pipecat/services/aws_nova_sonic/aws.py +82 -64
  105. pipecat/services/aws_nova_sonic/context.py +15 -6
  106. pipecat/services/azure/common.py +10 -2
  107. pipecat/services/azure/image.py +32 -0
  108. pipecat/services/azure/llm.py +9 -7
  109. pipecat/services/azure/stt.py +65 -2
  110. pipecat/services/azure/tts.py +154 -23
  111. pipecat/services/cartesia/stt.py +125 -8
  112. pipecat/services/cartesia/tts.py +102 -38
  113. pipecat/services/cerebras/llm.py +15 -23
  114. pipecat/services/deepgram/stt.py +19 -11
  115. pipecat/services/deepgram/tts.py +36 -0
  116. pipecat/services/deepseek/llm.py +14 -23
  117. pipecat/services/elevenlabs/tts.py +330 -64
  118. pipecat/services/fal/image.py +43 -0
  119. pipecat/services/fal/stt.py +48 -10
  120. pipecat/services/fireworks/llm.py +14 -21
  121. pipecat/services/fish/tts.py +109 -9
  122. pipecat/services/gemini_multimodal_live/__init__.py +1 -0
  123. pipecat/services/gemini_multimodal_live/events.py +83 -2
  124. pipecat/services/gemini_multimodal_live/file_api.py +189 -0
  125. pipecat/services/gemini_multimodal_live/gemini.py +218 -21
  126. pipecat/services/gladia/config.py +17 -10
  127. pipecat/services/gladia/stt.py +82 -36
  128. pipecat/services/google/frames.py +40 -0
  129. pipecat/services/google/google.py +2 -0
  130. pipecat/services/google/image.py +39 -2
  131. pipecat/services/google/llm.py +176 -58
  132. pipecat/services/google/llm_openai.py +26 -4
  133. pipecat/services/google/llm_vertex.py +37 -15
  134. pipecat/services/google/rtvi.py +41 -0
  135. pipecat/services/google/stt.py +65 -17
  136. pipecat/services/google/test-google-chirp.py +45 -0
  137. pipecat/services/google/tts.py +390 -19
  138. pipecat/services/grok/llm.py +8 -6
  139. pipecat/services/groq/llm.py +8 -6
  140. pipecat/services/groq/stt.py +13 -9
  141. pipecat/services/groq/tts.py +40 -0
  142. pipecat/services/hamsa/__init__.py +9 -0
  143. pipecat/services/hamsa/stt.py +241 -0
  144. pipecat/services/heygen/__init__.py +5 -0
  145. pipecat/services/heygen/api.py +281 -0
  146. pipecat/services/heygen/client.py +620 -0
  147. pipecat/services/heygen/video.py +338 -0
  148. pipecat/services/image_service.py +5 -3
  149. pipecat/services/inworld/__init__.py +1 -0
  150. pipecat/services/inworld/tts.py +592 -0
  151. pipecat/services/llm_service.py +127 -45
  152. pipecat/services/lmnt/tts.py +80 -7
  153. pipecat/services/mcp_service.py +85 -44
  154. pipecat/services/mem0/memory.py +42 -13
  155. pipecat/services/minimax/tts.py +74 -15
  156. pipecat/services/mistral/__init__.py +0 -0
  157. pipecat/services/mistral/llm.py +185 -0
  158. pipecat/services/moondream/vision.py +55 -10
  159. pipecat/services/neuphonic/tts.py +275 -48
  160. pipecat/services/nim/llm.py +8 -6
  161. pipecat/services/ollama/llm.py +27 -7
  162. pipecat/services/openai/base_llm.py +54 -16
  163. pipecat/services/openai/image.py +30 -0
  164. pipecat/services/openai/llm.py +7 -5
  165. pipecat/services/openai/stt.py +13 -9
  166. pipecat/services/openai/tts.py +42 -10
  167. pipecat/services/openai_realtime_beta/azure.py +11 -9
  168. pipecat/services/openai_realtime_beta/context.py +7 -5
  169. pipecat/services/openai_realtime_beta/events.py +10 -7
  170. pipecat/services/openai_realtime_beta/openai.py +37 -18
  171. pipecat/services/openpipe/llm.py +30 -24
  172. pipecat/services/openrouter/llm.py +9 -7
  173. pipecat/services/perplexity/llm.py +15 -19
  174. pipecat/services/piper/tts.py +26 -12
  175. pipecat/services/playht/tts.py +227 -65
  176. pipecat/services/qwen/llm.py +8 -6
  177. pipecat/services/rime/tts.py +128 -17
  178. pipecat/services/riva/stt.py +160 -22
  179. pipecat/services/riva/tts.py +67 -2
  180. pipecat/services/sambanova/llm.py +19 -17
  181. pipecat/services/sambanova/stt.py +14 -8
  182. pipecat/services/sarvam/tts.py +60 -13
  183. pipecat/services/simli/video.py +82 -21
  184. pipecat/services/soniox/__init__.py +0 -0
  185. pipecat/services/soniox/stt.py +398 -0
  186. pipecat/services/speechmatics/stt.py +29 -17
  187. pipecat/services/stt_service.py +47 -11
  188. pipecat/services/tavus/video.py +94 -25
  189. pipecat/services/together/llm.py +8 -6
  190. pipecat/services/tts_service.py +77 -53
  191. pipecat/services/ultravox/stt.py +46 -43
  192. pipecat/services/vision_service.py +5 -3
  193. pipecat/services/websocket_service.py +12 -11
  194. pipecat/services/whisper/base_stt.py +58 -12
  195. pipecat/services/whisper/stt.py +69 -58
  196. pipecat/services/xtts/tts.py +59 -2
  197. pipecat/sync/base_notifier.py +19 -0
  198. pipecat/sync/event_notifier.py +24 -0
  199. pipecat/tests/utils.py +73 -5
  200. pipecat/transcriptions/language.py +24 -0
  201. pipecat/transports/base_input.py +112 -8
  202. pipecat/transports/base_output.py +235 -13
  203. pipecat/transports/base_transport.py +119 -0
  204. pipecat/transports/local/audio.py +76 -0
  205. pipecat/transports/local/tk.py +84 -0
  206. pipecat/transports/network/fastapi_websocket.py +174 -15
  207. pipecat/transports/network/small_webrtc.py +383 -39
  208. pipecat/transports/network/webrtc_connection.py +214 -8
  209. pipecat/transports/network/websocket_client.py +171 -1
  210. pipecat/transports/network/websocket_server.py +147 -9
  211. pipecat/transports/services/daily.py +792 -70
  212. pipecat/transports/services/helpers/daily_rest.py +122 -129
  213. pipecat/transports/services/livekit.py +339 -4
  214. pipecat/transports/services/tavus.py +273 -38
  215. pipecat/utils/asyncio/task_manager.py +92 -186
  216. pipecat/utils/base_object.py +83 -1
  217. pipecat/utils/network.py +2 -0
  218. pipecat/utils/string.py +114 -58
  219. pipecat/utils/text/base_text_aggregator.py +44 -13
  220. pipecat/utils/text/base_text_filter.py +46 -0
  221. pipecat/utils/text/markdown_text_filter.py +70 -14
  222. pipecat/utils/text/pattern_pair_aggregator.py +18 -14
  223. pipecat/utils/text/simple_text_aggregator.py +43 -2
  224. pipecat/utils/text/skip_tags_aggregator.py +21 -13
  225. pipecat/utils/time.py +36 -0
  226. pipecat/utils/tracing/class_decorators.py +32 -7
  227. pipecat/utils/tracing/conversation_context_provider.py +12 -2
  228. pipecat/utils/tracing/service_attributes.py +80 -64
  229. pipecat/utils/tracing/service_decorators.py +48 -21
  230. pipecat/utils/tracing/setup.py +13 -7
  231. pipecat/utils/tracing/turn_context_provider.py +12 -2
  232. pipecat/utils/tracing/turn_trace_observer.py +27 -0
  233. pipecat/utils/utils.py +14 -14
  234. dv_pipecat_ai-0.0.74.dev770.dist-info/RECORD +0 -319
  235. pipecat/examples/daily_runner.py +0 -64
  236. pipecat/examples/run.py +0 -265
  237. pipecat/utils/asyncio/watchdog_async_iterator.py +0 -72
  238. pipecat/utils/asyncio/watchdog_event.py +0 -42
  239. pipecat/utils/asyncio/watchdog_priority_queue.py +0 -48
  240. pipecat/utils/asyncio/watchdog_queue.py +0 -48
  241. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/WHEEL +0 -0
  242. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/licenses/LICENSE +0 -0
  243. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/top_level.txt +0 -0
  244. /pipecat/{examples → extensions}/__init__.py +0 -0
@@ -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
- """This is a simple text aggregator. It aggregates text until an end of
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 pattern pair aggregator.
34
+ """Initialize the skip tags aggregator.
29
35
 
30
- Creates an empty aggregator with no patterns or handlers registered.
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 and process pattern pairs.
55
+ """Aggregate text while respecting tag boundaries.
48
56
 
49
- This method adds the new text to the buffer, processes any complete pattern
50
- pairs, and returns processed text up to sentence boundaries if possible.
51
- If there are incomplete patterns (start without matching end), it will
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, or None if more
59
- text is needed to form a complete sentence or pattern.
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
- Attributes:
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
- """Returns the OpenTelemetry meter instance.
74
+ """Get the OpenTelemetry meter instance.
75
75
 
76
76
  Returns:
77
- Meter: The OpenTelemetry meter instance for this object.
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
- """Adds tracing to an async function in a Traceable class.
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
- """Makes a class traceable for OpenTelemetry.
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
- settings: Service configuration settings
133
- vad_enabled: Whether voice activity detection is enabled
134
- ttfb: Time to first byte in seconds
135
- **kwargs: Additional attributes to add
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")