voiceground 0.1.4__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.
- voiceground/__init__.py +38 -0
- voiceground/_static/index.html +63 -0
- voiceground/events.py +72 -0
- voiceground/metrics.py +164 -0
- voiceground/observer.py +546 -0
- voiceground/py.typed +0 -0
- voiceground/reporters/__init__.py +19 -0
- voiceground/reporters/base.py +43 -0
- voiceground/reporters/html.py +238 -0
- voiceground/reporters/metrics.py +468 -0
- voiceground-0.1.4.dist-info/METADATA +199 -0
- voiceground-0.1.4.dist-info/RECORD +14 -0
- voiceground-0.1.4.dist-info/WHEEL +4 -0
- voiceground-0.1.4.dist-info/licenses/LICENSE +26 -0
voiceground/events.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Voiceground event types for conversation observability."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EventCategory(str, Enum):
|
|
10
|
+
"""Categories of conversation events."""
|
|
11
|
+
|
|
12
|
+
USER_SPEAK = "user_speak"
|
|
13
|
+
BOT_SPEAK = "bot_speak"
|
|
14
|
+
STT = "stt"
|
|
15
|
+
LLM = "llm"
|
|
16
|
+
TTS = "tts"
|
|
17
|
+
TOOL_CALL = "tool_call"
|
|
18
|
+
SYSTEM = "system"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EventType(str, Enum):
|
|
22
|
+
"""Types of events within each category."""
|
|
23
|
+
|
|
24
|
+
START = "start"
|
|
25
|
+
END = "end"
|
|
26
|
+
FIRST_BYTE = "first_byte"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class VoicegroundEvent:
|
|
31
|
+
"""A normalized conversation event.
|
|
32
|
+
|
|
33
|
+
Attributes:
|
|
34
|
+
id: Unique identifier for this event.
|
|
35
|
+
timestamp: Unix timestamp in seconds when the event occurred.
|
|
36
|
+
category: The category of the event (user_speak, bot_speak, stt, llm, tts, tool_call, system).
|
|
37
|
+
type: The type of event (start, end, first_byte).
|
|
38
|
+
source: The name of the processor/frame source that triggered this event.
|
|
39
|
+
data: Additional event-specific data.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
id: str
|
|
43
|
+
timestamp: float
|
|
44
|
+
category: EventCategory
|
|
45
|
+
type: EventType
|
|
46
|
+
source: str = ""
|
|
47
|
+
data: dict[str, Any] = field(default_factory=dict)
|
|
48
|
+
|
|
49
|
+
def to_dict(self) -> dict[str, Any]:
|
|
50
|
+
"""Convert the event to a dictionary for JSON serialization."""
|
|
51
|
+
return {
|
|
52
|
+
"id": self.id,
|
|
53
|
+
"timestamp": self.timestamp,
|
|
54
|
+
"category": self.category.value,
|
|
55
|
+
"type": self.type.value,
|
|
56
|
+
"source": self.source,
|
|
57
|
+
"data": self.data,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def from_dict(cls, data: dict[str, Any]) -> "VoicegroundEvent":
|
|
62
|
+
"""Create an event from a dictionary."""
|
|
63
|
+
# Generate ID if not present (for backward compatibility)
|
|
64
|
+
event_id = data.get("id") or str(uuid.uuid4())
|
|
65
|
+
return cls(
|
|
66
|
+
id=event_id,
|
|
67
|
+
timestamp=data["timestamp"],
|
|
68
|
+
category=EventCategory(data["category"]),
|
|
69
|
+
type=EventType(data["type"]),
|
|
70
|
+
source=data.get("source", ""),
|
|
71
|
+
data=data.get("data", {}),
|
|
72
|
+
)
|
voiceground/metrics.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Voiceground custom metrics frame classes for opinionated metrics."""
|
|
2
|
+
|
|
3
|
+
from pipecat.frames.frames import MetricsFrame
|
|
4
|
+
from pipecat.metrics.metrics import MetricsData
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class VoicegroundMetricsData(MetricsData):
|
|
8
|
+
"""Base class for all Voiceground metrics data.
|
|
9
|
+
|
|
10
|
+
Automatically sets processor="voiceground" for all metrics.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
processor: str = "voiceground"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TurnDurationMetricsData(VoicegroundMetricsData):
|
|
17
|
+
"""Turn Duration metrics data."""
|
|
18
|
+
|
|
19
|
+
value: float
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ResponseTimeMetricsData(VoicegroundMetricsData):
|
|
23
|
+
"""Response Time metrics data."""
|
|
24
|
+
|
|
25
|
+
value: float
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TranscriptionOverheadMetricsData(VoicegroundMetricsData):
|
|
29
|
+
"""Transcription Overhead metrics data."""
|
|
30
|
+
|
|
31
|
+
value: float
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class VoiceSynthesisOverheadMetricsData(VoicegroundMetricsData):
|
|
35
|
+
"""Voice Synthesis Overhead metrics data."""
|
|
36
|
+
|
|
37
|
+
value: float
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class LLMResponseTimeMetricsData(VoicegroundMetricsData):
|
|
41
|
+
"""LLM Response Time metrics data."""
|
|
42
|
+
|
|
43
|
+
value: float
|
|
44
|
+
net_value: float | None = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SystemOverheadMetricsData(VoicegroundMetricsData):
|
|
48
|
+
"""System Overhead metrics data."""
|
|
49
|
+
|
|
50
|
+
value: float
|
|
51
|
+
operation_name: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ToolUsageMetricsData(VoicegroundMetricsData):
|
|
55
|
+
"""Tool Usage metrics data."""
|
|
56
|
+
|
|
57
|
+
value: float
|
|
58
|
+
tool_name: str
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class VoicegroundMetricFrame(MetricsFrame):
|
|
62
|
+
"""Base class for all Voiceground metric frames.
|
|
63
|
+
|
|
64
|
+
Automatically sets up the MetricsFrame with the metric data and name.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
name: str = ""
|
|
68
|
+
|
|
69
|
+
def __init__(self, metric_data: MetricsData, name: str):
|
|
70
|
+
super().__init__(data=[metric_data])
|
|
71
|
+
self.name = name
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class VoicegroundTurnDurationFrame(VoicegroundMetricFrame):
|
|
75
|
+
"""Turn Duration metric frame: Total time from first event to last event in the turn.
|
|
76
|
+
|
|
77
|
+
Parameters:
|
|
78
|
+
value: Turn duration in seconds.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, value: float):
|
|
82
|
+
metric_data = TurnDurationMetricsData(processor="voiceground", value=value)
|
|
83
|
+
super().__init__(metric_data, "turn_duration")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class VoicegroundResponseTimeFrame(VoicegroundMetricFrame):
|
|
87
|
+
"""Response Time metric frame: Time from user_speak:end to bot_speak:start.
|
|
88
|
+
|
|
89
|
+
Parameters:
|
|
90
|
+
value: Response time in seconds.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __init__(self, value: float):
|
|
94
|
+
metric_data = ResponseTimeMetricsData(processor="voiceground", value=value)
|
|
95
|
+
super().__init__(metric_data, "response_time")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class VoicegroundTranscriptionOverheadFrame(VoicegroundMetricFrame):
|
|
99
|
+
"""Transcription Overhead metric frame: Time from user_speak:end to stt:end.
|
|
100
|
+
|
|
101
|
+
Parameters:
|
|
102
|
+
value: Transcription overhead in seconds.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
def __init__(self, value: float):
|
|
106
|
+
metric_data = TranscriptionOverheadMetricsData(processor="voiceground", value=value)
|
|
107
|
+
super().__init__(metric_data, "transcription_overhead")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class VoicegroundVoiceSynthesisOverheadFrame(VoicegroundMetricFrame):
|
|
111
|
+
"""Voice Synthesis Overhead metric frame: Time from tts:start to bot_speak:start.
|
|
112
|
+
|
|
113
|
+
Parameters:
|
|
114
|
+
value: Voice synthesis overhead in seconds.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def __init__(self, value: float):
|
|
118
|
+
metric_data = VoiceSynthesisOverheadMetricsData(processor="voiceground", value=value)
|
|
119
|
+
super().__init__(metric_data, "voice_synthesis_overhead")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class VoicegroundLLMResponseTimeFrame(VoicegroundMetricFrame):
|
|
123
|
+
"""LLM Response Time metric frame: Time from llm:start to llm:first_byte.
|
|
124
|
+
|
|
125
|
+
Parameters:
|
|
126
|
+
value: LLM response time in seconds (includes tools overhead).
|
|
127
|
+
net_value: LLM response time in seconds excluding tools overhead.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
def __init__(self, value: float, net_value: float | None = None):
|
|
131
|
+
metric_data = LLMResponseTimeMetricsData(
|
|
132
|
+
processor="voiceground", value=value, net_value=net_value
|
|
133
|
+
)
|
|
134
|
+
super().__init__(metric_data, "llm_response_time")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class VoicegroundSystemOverheadFrame(VoicegroundMetricFrame):
|
|
138
|
+
"""System Overhead metric frame: Duration of a specific system operation.
|
|
139
|
+
|
|
140
|
+
Parameters:
|
|
141
|
+
value: System overhead in seconds.
|
|
142
|
+
operation_name: Name/type of the system operation (e.g., "context_aggregation_timeout").
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(self, value: float, operation_name: str):
|
|
146
|
+
metric_data = SystemOverheadMetricsData(
|
|
147
|
+
processor="voiceground", value=value, operation_name=operation_name
|
|
148
|
+
)
|
|
149
|
+
super().__init__(metric_data, f"system_overhead_{operation_name}")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class VoicegroundToolUsageFrame(VoicegroundMetricFrame):
|
|
153
|
+
"""Individual Tool Usage metric frame: Duration of a specific tool call.
|
|
154
|
+
|
|
155
|
+
Parameters:
|
|
156
|
+
value: Tool call duration in seconds.
|
|
157
|
+
tool_name: Name of the tool/function that was called.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def __init__(self, value: float, tool_name: str):
|
|
161
|
+
metric_data = ToolUsageMetricsData(
|
|
162
|
+
processor="voiceground", value=value, tool_name=tool_name
|
|
163
|
+
)
|
|
164
|
+
super().__init__(metric_data, f"tool_usage_{tool_name}")
|