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
|
+
"""RTVI (Real-Time Voice Interface) protocol implementation for Pipecat.
|
|
8
|
+
|
|
9
|
+
This module provides the RTVI protocol implementation for real-time voice interactions
|
|
10
|
+
between clients and AI agents. It includes message handling, action processing,
|
|
11
|
+
and frame observation for the RTVI protocol.
|
|
12
|
+
"""
|
|
13
|
+
|
|
7
14
|
import asyncio
|
|
8
15
|
import base64
|
|
9
16
|
from dataclasses import dataclass
|
|
@@ -37,6 +44,7 @@ from pipecat.frames.frames import (
|
|
|
37
44
|
InterimTranscriptionFrame,
|
|
38
45
|
LLMFullResponseEndFrame,
|
|
39
46
|
LLMFullResponseStartFrame,
|
|
47
|
+
LLMMessagesAppendFrame,
|
|
40
48
|
LLMTextFrame,
|
|
41
49
|
MetricsFrame,
|
|
42
50
|
StartFrame,
|
|
@@ -67,10 +75,9 @@ from pipecat.services.llm_service import (
|
|
|
67
75
|
from pipecat.transports.base_input import BaseInputTransport
|
|
68
76
|
from pipecat.transports.base_output import BaseOutputTransport
|
|
69
77
|
from pipecat.transports.base_transport import BaseTransport
|
|
70
|
-
from pipecat.utils.asyncio.watchdog_queue import WatchdogQueue
|
|
71
78
|
from pipecat.utils.string import match_endofsentence
|
|
72
79
|
|
|
73
|
-
RTVI_PROTOCOL_VERSION = "0.
|
|
80
|
+
RTVI_PROTOCOL_VERSION = "1.0.0"
|
|
74
81
|
|
|
75
82
|
RTVI_MESSAGE_LABEL = "rtvi-ai"
|
|
76
83
|
RTVIMessageLiteral = Literal["rtvi-ai"]
|
|
@@ -79,6 +86,16 @@ ActionResult = Union[bool, int, float, str, list, dict]
|
|
|
79
86
|
|
|
80
87
|
|
|
81
88
|
class RTVIServiceOption(BaseModel):
|
|
89
|
+
"""Configuration option for an RTVI service.
|
|
90
|
+
|
|
91
|
+
Defines a configurable option that can be set for an RTVI service,
|
|
92
|
+
including its name, type, and handler function.
|
|
93
|
+
|
|
94
|
+
.. deprecated:: 0.0.75
|
|
95
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
96
|
+
Use custom client and server messages instead.
|
|
97
|
+
"""
|
|
98
|
+
|
|
82
99
|
name: str
|
|
83
100
|
type: Literal["bool", "number", "string", "array", "object"]
|
|
84
101
|
handler: Callable[["RTVIProcessor", str, "RTVIServiceOptionConfig"], Awaitable[None]] = Field(
|
|
@@ -87,11 +104,22 @@ class RTVIServiceOption(BaseModel):
|
|
|
87
104
|
|
|
88
105
|
|
|
89
106
|
class RTVIService(BaseModel):
|
|
107
|
+
"""An RTVI service definition.
|
|
108
|
+
|
|
109
|
+
Represents a service that can be configured and used within the RTVI protocol,
|
|
110
|
+
containing a name and list of configurable options.
|
|
111
|
+
|
|
112
|
+
.. deprecated:: 0.0.75
|
|
113
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
114
|
+
Use custom client and server messages instead.
|
|
115
|
+
"""
|
|
116
|
+
|
|
90
117
|
name: str
|
|
91
118
|
options: List[RTVIServiceOption]
|
|
92
119
|
_options_dict: Dict[str, RTVIServiceOption] = PrivateAttr(default={})
|
|
93
120
|
|
|
94
121
|
def model_post_init(self, __context: Any) -> None:
|
|
122
|
+
"""Initialize the options dictionary after model creation."""
|
|
95
123
|
self._options_dict = {}
|
|
96
124
|
for option in self.options:
|
|
97
125
|
self._options_dict[option.name] = option
|
|
@@ -99,16 +127,44 @@ class RTVIService(BaseModel):
|
|
|
99
127
|
|
|
100
128
|
|
|
101
129
|
class RTVIActionArgumentData(BaseModel):
|
|
130
|
+
"""Data for an RTVI action argument.
|
|
131
|
+
|
|
132
|
+
Contains the name and value of an argument passed to an RTVI action.
|
|
133
|
+
|
|
134
|
+
.. deprecated:: 0.0.75
|
|
135
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
136
|
+
Use custom client and server messages instead.
|
|
137
|
+
"""
|
|
138
|
+
|
|
102
139
|
name: str
|
|
103
140
|
value: Any
|
|
104
141
|
|
|
105
142
|
|
|
106
143
|
class RTVIActionArgument(BaseModel):
|
|
144
|
+
"""Definition of an RTVI action argument.
|
|
145
|
+
|
|
146
|
+
Specifies the name and expected type of an argument for an RTVI action.
|
|
147
|
+
|
|
148
|
+
.. deprecated:: 0.0.75
|
|
149
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
150
|
+
Use custom client and server messages instead.
|
|
151
|
+
"""
|
|
152
|
+
|
|
107
153
|
name: str
|
|
108
154
|
type: Literal["bool", "number", "string", "array", "object"]
|
|
109
155
|
|
|
110
156
|
|
|
111
157
|
class RTVIAction(BaseModel):
|
|
158
|
+
"""An RTVI action definition.
|
|
159
|
+
|
|
160
|
+
Represents an action that can be executed within the RTVI protocol,
|
|
161
|
+
including its service, name, arguments, and handler function.
|
|
162
|
+
|
|
163
|
+
.. deprecated:: 0.0.75
|
|
164
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
165
|
+
Use custom client and server messages instead.
|
|
166
|
+
"""
|
|
167
|
+
|
|
112
168
|
service: str
|
|
113
169
|
action: str
|
|
114
170
|
arguments: List[RTVIActionArgument] = Field(default_factory=list)
|
|
@@ -119,6 +175,7 @@ class RTVIAction(BaseModel):
|
|
|
119
175
|
_arguments_dict: Dict[str, RTVIActionArgument] = PrivateAttr(default={})
|
|
120
176
|
|
|
121
177
|
def model_post_init(self, __context: Any) -> None:
|
|
178
|
+
"""Initialize the arguments dictionary after model creation."""
|
|
122
179
|
self._arguments_dict = {}
|
|
123
180
|
for arg in self.arguments:
|
|
124
181
|
self._arguments_dict[arg.name] = arg
|
|
@@ -126,16 +183,43 @@ class RTVIAction(BaseModel):
|
|
|
126
183
|
|
|
127
184
|
|
|
128
185
|
class RTVIServiceOptionConfig(BaseModel):
|
|
186
|
+
"""Configuration value for an RTVI service option.
|
|
187
|
+
|
|
188
|
+
Contains the name and value to set for a specific service option.
|
|
189
|
+
|
|
190
|
+
.. deprecated:: 0.0.75
|
|
191
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
192
|
+
Use custom client and server messages instead.
|
|
193
|
+
"""
|
|
194
|
+
|
|
129
195
|
name: str
|
|
130
196
|
value: Any
|
|
131
197
|
|
|
132
198
|
|
|
133
199
|
class RTVIServiceConfig(BaseModel):
|
|
200
|
+
"""Configuration for an RTVI service.
|
|
201
|
+
|
|
202
|
+
Contains the service name and list of option configurations to apply.
|
|
203
|
+
|
|
204
|
+
.. deprecated:: 0.0.75
|
|
205
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
206
|
+
Use custom client and server messages instead.
|
|
207
|
+
"""
|
|
208
|
+
|
|
134
209
|
service: str
|
|
135
210
|
options: List[RTVIServiceOptionConfig]
|
|
136
211
|
|
|
137
212
|
|
|
138
213
|
class RTVIConfig(BaseModel):
|
|
214
|
+
"""Complete RTVI configuration.
|
|
215
|
+
|
|
216
|
+
Contains the full configuration for all RTVI services.
|
|
217
|
+
|
|
218
|
+
.. deprecated:: 0.0.75
|
|
219
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
220
|
+
Use custom client and server messages instead.
|
|
221
|
+
"""
|
|
222
|
+
|
|
139
223
|
config: List[RTVIServiceConfig]
|
|
140
224
|
|
|
141
225
|
|
|
@@ -144,17 +228,45 @@ class RTVIConfig(BaseModel):
|
|
|
144
228
|
#
|
|
145
229
|
|
|
146
230
|
|
|
231
|
+
# deprecated
|
|
147
232
|
class RTVIUpdateConfig(BaseModel):
|
|
233
|
+
"""Request to update RTVI configuration.
|
|
234
|
+
|
|
235
|
+
Contains new configuration settings and whether to interrupt the bot.
|
|
236
|
+
|
|
237
|
+
.. deprecated:: 0.0.75
|
|
238
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
239
|
+
Use custom client and server messages instead.
|
|
240
|
+
"""
|
|
241
|
+
|
|
148
242
|
config: List[RTVIServiceConfig]
|
|
149
243
|
interrupt: bool = False
|
|
150
244
|
|
|
151
245
|
|
|
152
246
|
class RTVIActionRunArgument(BaseModel):
|
|
247
|
+
"""Argument for running an RTVI action.
|
|
248
|
+
|
|
249
|
+
Contains the name and value of an argument to pass to an action.
|
|
250
|
+
|
|
251
|
+
.. deprecated:: 0.0.75
|
|
252
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
253
|
+
Use custom client and server messages instead.
|
|
254
|
+
"""
|
|
255
|
+
|
|
153
256
|
name: str
|
|
154
257
|
value: Any
|
|
155
258
|
|
|
156
259
|
|
|
157
260
|
class RTVIActionRun(BaseModel):
|
|
261
|
+
"""Request to run an RTVI action.
|
|
262
|
+
|
|
263
|
+
Contains the service, action name, and optional arguments.
|
|
264
|
+
|
|
265
|
+
.. deprecated:: 0.0.75
|
|
266
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
267
|
+
Use custom client and server messages instead.
|
|
268
|
+
"""
|
|
269
|
+
|
|
158
270
|
service: str
|
|
159
271
|
action: str
|
|
160
272
|
arguments: Optional[List[RTVIActionRunArgument]] = None
|
|
@@ -162,11 +274,91 @@ class RTVIActionRun(BaseModel):
|
|
|
162
274
|
|
|
163
275
|
@dataclass
|
|
164
276
|
class RTVIActionFrame(DataFrame):
|
|
277
|
+
"""Frame containing an RTVI action to execute.
|
|
278
|
+
|
|
279
|
+
Parameters:
|
|
280
|
+
rtvi_action_run: The action to execute.
|
|
281
|
+
message_id: Optional message ID for response correlation.
|
|
282
|
+
|
|
283
|
+
.. deprecated:: 0.0.75
|
|
284
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
285
|
+
Use custom client and server messages instead.
|
|
286
|
+
"""
|
|
287
|
+
|
|
165
288
|
rtvi_action_run: RTVIActionRun
|
|
166
289
|
message_id: Optional[str] = None
|
|
167
290
|
|
|
168
291
|
|
|
292
|
+
class RTVIRawClientMessageData(BaseModel):
|
|
293
|
+
"""Data structure expected from client messages sent to the RTVI server."""
|
|
294
|
+
|
|
295
|
+
t: str
|
|
296
|
+
d: Optional[Any] = None
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class RTVIClientMessage(BaseModel):
|
|
300
|
+
"""Cleansed data structure for client messages for handling."""
|
|
301
|
+
|
|
302
|
+
msg_id: str
|
|
303
|
+
type: str
|
|
304
|
+
data: Optional[Any] = None
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@dataclass
|
|
308
|
+
class RTVIClientMessageFrame(SystemFrame):
|
|
309
|
+
"""A frame for sending messages from the client to the RTVI server.
|
|
310
|
+
|
|
311
|
+
This frame is meant for custom messaging from the client to the server
|
|
312
|
+
and expects a server-response message.
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
msg_id: str
|
|
316
|
+
type: str
|
|
317
|
+
data: Optional[Any] = None
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@dataclass
|
|
321
|
+
class RTVIServerResponseFrame(SystemFrame):
|
|
322
|
+
"""A frame for responding to a client RTVI message.
|
|
323
|
+
|
|
324
|
+
This frame should be sent in response to an RTVIClientMessageFrame
|
|
325
|
+
and include the original RTVIClientMessageFrame to ensure the response
|
|
326
|
+
is properly attributed to the original request. To respond with an error,
|
|
327
|
+
set the `error` field to a string describing the error. This will result
|
|
328
|
+
in the client receiving a `response-error` message instead of a
|
|
329
|
+
`server-response` message.
|
|
330
|
+
"""
|
|
331
|
+
|
|
332
|
+
client_msg: RTVIClientMessageFrame
|
|
333
|
+
data: Optional[Any] = None
|
|
334
|
+
error: Optional[str] = None
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class RTVIRawServerResponseData(BaseModel):
|
|
338
|
+
"""Data structure for server responses to client messages."""
|
|
339
|
+
|
|
340
|
+
t: str
|
|
341
|
+
d: Optional[Any] = None
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class RTVIServerResponse(BaseModel):
|
|
345
|
+
"""The RTVI-formatted message response from the server to the client.
|
|
346
|
+
|
|
347
|
+
This message is used to respond to custom messages sent by the client.
|
|
348
|
+
"""
|
|
349
|
+
|
|
350
|
+
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
351
|
+
type: Literal["server-response"] = "server-response"
|
|
352
|
+
id: str
|
|
353
|
+
data: RTVIRawServerResponseData
|
|
354
|
+
|
|
355
|
+
|
|
169
356
|
class RTVIMessage(BaseModel):
|
|
357
|
+
"""Base RTVI message structure.
|
|
358
|
+
|
|
359
|
+
Represents the standard format for RTVI protocol messages.
|
|
360
|
+
"""
|
|
361
|
+
|
|
170
362
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
171
363
|
type: str
|
|
172
364
|
id: str
|
|
@@ -179,10 +371,20 @@ class RTVIMessage(BaseModel):
|
|
|
179
371
|
|
|
180
372
|
|
|
181
373
|
class RTVIErrorResponseData(BaseModel):
|
|
374
|
+
"""Data for an RTVI error response.
|
|
375
|
+
|
|
376
|
+
Contains the error message to send back to the client.
|
|
377
|
+
"""
|
|
378
|
+
|
|
182
379
|
error: str
|
|
183
380
|
|
|
184
381
|
|
|
185
382
|
class RTVIErrorResponse(BaseModel):
|
|
383
|
+
"""RTVI error response message.
|
|
384
|
+
|
|
385
|
+
RTVI Formatted error response message for relaying failed client requests.
|
|
386
|
+
"""
|
|
387
|
+
|
|
186
388
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
187
389
|
type: Literal["error-response"] = "error-response"
|
|
188
390
|
id: str
|
|
@@ -190,21 +392,49 @@ class RTVIErrorResponse(BaseModel):
|
|
|
190
392
|
|
|
191
393
|
|
|
192
394
|
class RTVIErrorData(BaseModel):
|
|
395
|
+
"""Data for an RTVI error event.
|
|
396
|
+
|
|
397
|
+
Contains error information including whether it's fatal.
|
|
398
|
+
"""
|
|
399
|
+
|
|
193
400
|
error: str
|
|
194
|
-
fatal: bool
|
|
401
|
+
fatal: bool # Indicates the pipeline has stopped due to this error
|
|
195
402
|
|
|
196
403
|
|
|
197
404
|
class RTVIError(BaseModel):
|
|
405
|
+
"""RTVI error event message.
|
|
406
|
+
|
|
407
|
+
RTVI Formatted error message for relaying errors in the pipeline.
|
|
408
|
+
"""
|
|
409
|
+
|
|
198
410
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
199
411
|
type: Literal["error"] = "error"
|
|
200
412
|
data: RTVIErrorData
|
|
201
413
|
|
|
202
414
|
|
|
203
415
|
class RTVIDescribeConfigData(BaseModel):
|
|
416
|
+
"""Data for describing available RTVI configuration.
|
|
417
|
+
|
|
418
|
+
Contains the list of available services and their options.
|
|
419
|
+
|
|
420
|
+
.. deprecated:: 0.0.75
|
|
421
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
422
|
+
Use custom client and server messages instead.
|
|
423
|
+
"""
|
|
424
|
+
|
|
204
425
|
config: List[RTVIService]
|
|
205
426
|
|
|
206
427
|
|
|
207
428
|
class RTVIDescribeConfig(BaseModel):
|
|
429
|
+
"""Message describing available RTVI configuration.
|
|
430
|
+
|
|
431
|
+
Sent in response to a describe-config request.
|
|
432
|
+
|
|
433
|
+
.. deprecated:: 0.0.75
|
|
434
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
435
|
+
Use custom client and server messages instead.
|
|
436
|
+
"""
|
|
437
|
+
|
|
208
438
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
209
439
|
type: Literal["config-available"] = "config-available"
|
|
210
440
|
id: str
|
|
@@ -212,10 +442,28 @@ class RTVIDescribeConfig(BaseModel):
|
|
|
212
442
|
|
|
213
443
|
|
|
214
444
|
class RTVIDescribeActionsData(BaseModel):
|
|
445
|
+
"""Data for describing available RTVI actions.
|
|
446
|
+
|
|
447
|
+
Contains the list of available actions that can be executed.
|
|
448
|
+
|
|
449
|
+
.. deprecated:: 0.0.75
|
|
450
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
451
|
+
Use custom client and server messages instead.
|
|
452
|
+
"""
|
|
453
|
+
|
|
215
454
|
actions: List[RTVIAction]
|
|
216
455
|
|
|
217
456
|
|
|
218
457
|
class RTVIDescribeActions(BaseModel):
|
|
458
|
+
"""Message describing available RTVI actions.
|
|
459
|
+
|
|
460
|
+
Sent in response to a describe-actions request.
|
|
461
|
+
|
|
462
|
+
.. deprecated:: 0.0.75
|
|
463
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
464
|
+
Use custom client and server messages instead.
|
|
465
|
+
"""
|
|
466
|
+
|
|
219
467
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
220
468
|
type: Literal["actions-available"] = "actions-available"
|
|
221
469
|
id: str
|
|
@@ -223,6 +471,15 @@ class RTVIDescribeActions(BaseModel):
|
|
|
223
471
|
|
|
224
472
|
|
|
225
473
|
class RTVIConfigResponse(BaseModel):
|
|
474
|
+
"""Response containing current RTVI configuration.
|
|
475
|
+
|
|
476
|
+
Sent in response to a get-config request.
|
|
477
|
+
|
|
478
|
+
.. deprecated:: 0.0.75
|
|
479
|
+
Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0.
|
|
480
|
+
Use custom client and server messages instead.
|
|
481
|
+
"""
|
|
482
|
+
|
|
226
483
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
227
484
|
type: Literal["config"] = "config"
|
|
228
485
|
id: str
|
|
@@ -230,22 +487,77 @@ class RTVIConfigResponse(BaseModel):
|
|
|
230
487
|
|
|
231
488
|
|
|
232
489
|
class RTVIActionResponseData(BaseModel):
|
|
490
|
+
"""Data for an RTVI action response.
|
|
491
|
+
|
|
492
|
+
Contains the result of executing an action.
|
|
493
|
+
|
|
494
|
+
.. deprecated:: 0.0.75
|
|
495
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
496
|
+
Use custom client and server messages instead.
|
|
497
|
+
"""
|
|
498
|
+
|
|
233
499
|
result: ActionResult
|
|
234
500
|
|
|
235
501
|
|
|
236
502
|
class RTVIActionResponse(BaseModel):
|
|
503
|
+
"""Response to an RTVI action execution.
|
|
504
|
+
|
|
505
|
+
Sent after successfully executing an action.
|
|
506
|
+
|
|
507
|
+
.. deprecated:: 0.0.75
|
|
508
|
+
Actions have been removed as part of the RTVI protocol 1.0.0.
|
|
509
|
+
Use custom client and server messages instead.
|
|
510
|
+
"""
|
|
511
|
+
|
|
237
512
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
238
513
|
type: Literal["action-response"] = "action-response"
|
|
239
514
|
id: str
|
|
240
515
|
data: RTVIActionResponseData
|
|
241
516
|
|
|
242
517
|
|
|
518
|
+
class AboutClientData(BaseModel):
|
|
519
|
+
"""Data about the RTVI client.
|
|
520
|
+
|
|
521
|
+
Contains information about the client, including which RTVI library it
|
|
522
|
+
is using, what platform it is on and any additional details, if available.
|
|
523
|
+
"""
|
|
524
|
+
|
|
525
|
+
library: str
|
|
526
|
+
library_version: Optional[str] = None
|
|
527
|
+
platform: Optional[str] = None
|
|
528
|
+
platform_version: Optional[str] = None
|
|
529
|
+
platform_details: Optional[Any] = None
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
class RTVIClientReadyData(BaseModel):
|
|
533
|
+
"""Data format of client ready messages.
|
|
534
|
+
|
|
535
|
+
Contains the RTVIprotocol version and client information.
|
|
536
|
+
"""
|
|
537
|
+
|
|
538
|
+
version: str
|
|
539
|
+
about: AboutClientData
|
|
540
|
+
|
|
541
|
+
|
|
243
542
|
class RTVIBotReadyData(BaseModel):
|
|
543
|
+
"""Data for bot ready notification.
|
|
544
|
+
|
|
545
|
+
Contains protocol version and initial configuration.
|
|
546
|
+
"""
|
|
547
|
+
|
|
244
548
|
version: str
|
|
245
|
-
config
|
|
549
|
+
# The config field is deprecated and will not be included if
|
|
550
|
+
# the client's rtvi version is 1.0.0 or higher.
|
|
551
|
+
config: Optional[List[RTVIServiceConfig]] = None
|
|
552
|
+
about: Optional[Mapping[str, Any]] = None
|
|
246
553
|
|
|
247
554
|
|
|
248
555
|
class RTVIBotReady(BaseModel):
|
|
556
|
+
"""Message indicating bot is ready for interaction.
|
|
557
|
+
|
|
558
|
+
Sent after bot initialization is complete.
|
|
559
|
+
"""
|
|
560
|
+
|
|
249
561
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
250
562
|
type: Literal["bot-ready"] = "bot-ready"
|
|
251
563
|
id: str
|
|
@@ -253,28 +565,72 @@ class RTVIBotReady(BaseModel):
|
|
|
253
565
|
|
|
254
566
|
|
|
255
567
|
class RTVILLMFunctionCallMessageData(BaseModel):
|
|
568
|
+
"""Data for LLM function call notification.
|
|
569
|
+
|
|
570
|
+
Contains function call details including name, ID, and arguments.
|
|
571
|
+
"""
|
|
572
|
+
|
|
256
573
|
function_name: str
|
|
257
574
|
tool_call_id: str
|
|
258
575
|
args: Mapping[str, Any]
|
|
259
576
|
|
|
260
577
|
|
|
261
578
|
class RTVILLMFunctionCallMessage(BaseModel):
|
|
579
|
+
"""Message notifying of an LLM function call.
|
|
580
|
+
|
|
581
|
+
Sent when the LLM makes a function call.
|
|
582
|
+
"""
|
|
583
|
+
|
|
262
584
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
263
585
|
type: Literal["llm-function-call"] = "llm-function-call"
|
|
264
586
|
data: RTVILLMFunctionCallMessageData
|
|
265
587
|
|
|
266
588
|
|
|
589
|
+
class RTVIAppendToContextData(BaseModel):
|
|
590
|
+
"""Data format for appending messages to the context.
|
|
591
|
+
|
|
592
|
+
Contains the role, content, and whether to run the message immediately.
|
|
593
|
+
"""
|
|
594
|
+
|
|
595
|
+
role: Literal["user", "assistant"] | str
|
|
596
|
+
content: Any
|
|
597
|
+
run_immediately: bool = False
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
class RTVIAppendToContext(BaseModel):
|
|
601
|
+
"""RTVI Message format to append content to the LLM context."""
|
|
602
|
+
|
|
603
|
+
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
604
|
+
type: Literal["append-to-context"] = "append-to-context"
|
|
605
|
+
data: RTVIAppendToContextData
|
|
606
|
+
|
|
607
|
+
|
|
267
608
|
class RTVILLMFunctionCallStartMessageData(BaseModel):
|
|
609
|
+
"""Data for LLM function call start notification.
|
|
610
|
+
|
|
611
|
+
Contains the function name being called.
|
|
612
|
+
"""
|
|
613
|
+
|
|
268
614
|
function_name: str
|
|
269
615
|
|
|
270
616
|
|
|
271
617
|
class RTVILLMFunctionCallStartMessage(BaseModel):
|
|
618
|
+
"""Message notifying that an LLM function call has started.
|
|
619
|
+
|
|
620
|
+
Sent when the LLM begins a function call.
|
|
621
|
+
"""
|
|
622
|
+
|
|
272
623
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
273
624
|
type: Literal["llm-function-call-start"] = "llm-function-call-start"
|
|
274
625
|
data: RTVILLMFunctionCallStartMessageData
|
|
275
626
|
|
|
276
627
|
|
|
277
628
|
class RTVILLMFunctionCallResultData(BaseModel):
|
|
629
|
+
"""Data for LLM function call result.
|
|
630
|
+
|
|
631
|
+
Contains function call details and result.
|
|
632
|
+
"""
|
|
633
|
+
|
|
278
634
|
function_name: str
|
|
279
635
|
tool_call_id: str
|
|
280
636
|
arguments: dict
|
|
@@ -282,60 +638,103 @@ class RTVILLMFunctionCallResultData(BaseModel):
|
|
|
282
638
|
|
|
283
639
|
|
|
284
640
|
class RTVIBotLLMStartedMessage(BaseModel):
|
|
641
|
+
"""Message indicating bot LLM processing has started."""
|
|
642
|
+
|
|
285
643
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
286
644
|
type: Literal["bot-llm-started"] = "bot-llm-started"
|
|
287
645
|
|
|
288
646
|
|
|
289
647
|
class RTVIBotLLMStoppedMessage(BaseModel):
|
|
648
|
+
"""Message indicating bot LLM processing has stopped."""
|
|
649
|
+
|
|
290
650
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
291
651
|
type: Literal["bot-llm-stopped"] = "bot-llm-stopped"
|
|
292
652
|
|
|
293
653
|
|
|
294
654
|
class RTVIBotTTSStartedMessage(BaseModel):
|
|
655
|
+
"""Message indicating bot TTS processing has started."""
|
|
656
|
+
|
|
295
657
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
296
658
|
type: Literal["bot-tts-started"] = "bot-tts-started"
|
|
297
659
|
|
|
298
660
|
|
|
299
661
|
class RTVIBotTTSStoppedMessage(BaseModel):
|
|
662
|
+
"""Message indicating bot TTS processing has stopped."""
|
|
663
|
+
|
|
300
664
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
301
665
|
type: Literal["bot-tts-stopped"] = "bot-tts-stopped"
|
|
302
666
|
|
|
303
667
|
|
|
304
668
|
class RTVITextMessageData(BaseModel):
|
|
669
|
+
"""Data for text-based RTVI messages.
|
|
670
|
+
|
|
671
|
+
Contains text content.
|
|
672
|
+
"""
|
|
673
|
+
|
|
305
674
|
text: str
|
|
306
675
|
|
|
307
676
|
|
|
308
677
|
class RTVIBotTranscriptionMessage(BaseModel):
|
|
678
|
+
"""Message containing bot transcription text.
|
|
679
|
+
|
|
680
|
+
Sent when the bot's speech is transcribed.
|
|
681
|
+
"""
|
|
682
|
+
|
|
309
683
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
310
684
|
type: Literal["bot-transcription"] = "bot-transcription"
|
|
311
685
|
data: RTVITextMessageData
|
|
312
686
|
|
|
313
687
|
|
|
314
688
|
class RTVIBotLLMTextMessage(BaseModel):
|
|
689
|
+
"""Message containing bot LLM text output.
|
|
690
|
+
|
|
691
|
+
Sent when the bot's LLM generates text.
|
|
692
|
+
"""
|
|
693
|
+
|
|
315
694
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
316
695
|
type: Literal["bot-llm-text"] = "bot-llm-text"
|
|
317
696
|
data: RTVITextMessageData
|
|
318
697
|
|
|
319
698
|
|
|
320
699
|
class RTVIBotTTSTextMessage(BaseModel):
|
|
700
|
+
"""Message containing bot TTS text output.
|
|
701
|
+
|
|
702
|
+
Sent when text is being processed by TTS.
|
|
703
|
+
"""
|
|
704
|
+
|
|
321
705
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
322
706
|
type: Literal["bot-tts-text"] = "bot-tts-text"
|
|
323
707
|
data: RTVITextMessageData
|
|
324
708
|
|
|
325
709
|
|
|
326
710
|
class RTVIAudioMessageData(BaseModel):
|
|
711
|
+
"""Data for audio-based RTVI messages.
|
|
712
|
+
|
|
713
|
+
Contains audio data and metadata.
|
|
714
|
+
"""
|
|
715
|
+
|
|
327
716
|
audio: str
|
|
328
717
|
sample_rate: int
|
|
329
718
|
num_channels: int
|
|
330
719
|
|
|
331
720
|
|
|
332
721
|
class RTVIBotTTSAudioMessage(BaseModel):
|
|
722
|
+
"""Message containing bot TTS audio output.
|
|
723
|
+
|
|
724
|
+
Sent when the bot's TTS generates audio.
|
|
725
|
+
"""
|
|
726
|
+
|
|
333
727
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
334
728
|
type: Literal["bot-tts-audio"] = "bot-tts-audio"
|
|
335
729
|
data: RTVIAudioMessageData
|
|
336
730
|
|
|
337
731
|
|
|
338
732
|
class RTVIUserTranscriptionMessageData(BaseModel):
|
|
733
|
+
"""Data for user transcription messages.
|
|
734
|
+
|
|
735
|
+
Contains transcription text and metadata.
|
|
736
|
+
"""
|
|
737
|
+
|
|
339
738
|
text: str
|
|
340
739
|
user_id: str
|
|
341
740
|
timestamp: str
|
|
@@ -343,44 +742,72 @@ class RTVIUserTranscriptionMessageData(BaseModel):
|
|
|
343
742
|
|
|
344
743
|
|
|
345
744
|
class RTVIUserTranscriptionMessage(BaseModel):
|
|
745
|
+
"""Message containing user transcription.
|
|
746
|
+
|
|
747
|
+
Sent when user speech is transcribed.
|
|
748
|
+
"""
|
|
749
|
+
|
|
346
750
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
347
751
|
type: Literal["user-transcription"] = "user-transcription"
|
|
348
752
|
data: RTVIUserTranscriptionMessageData
|
|
349
753
|
|
|
350
754
|
|
|
351
755
|
class RTVIUserLLMTextMessage(BaseModel):
|
|
756
|
+
"""Message containing user text input for LLM.
|
|
757
|
+
|
|
758
|
+
Sent when user text is processed by the LLM.
|
|
759
|
+
"""
|
|
760
|
+
|
|
352
761
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
353
762
|
type: Literal["user-llm-text"] = "user-llm-text"
|
|
354
763
|
data: RTVITextMessageData
|
|
355
764
|
|
|
356
765
|
|
|
357
766
|
class RTVIUserStartedSpeakingMessage(BaseModel):
|
|
767
|
+
"""Message indicating user has started speaking."""
|
|
768
|
+
|
|
358
769
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
359
770
|
type: Literal["user-started-speaking"] = "user-started-speaking"
|
|
360
771
|
|
|
361
772
|
|
|
362
773
|
class RTVIUserStoppedSpeakingMessage(BaseModel):
|
|
774
|
+
"""Message indicating user has stopped speaking."""
|
|
775
|
+
|
|
363
776
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
364
777
|
type: Literal["user-stopped-speaking"] = "user-stopped-speaking"
|
|
365
778
|
|
|
366
779
|
|
|
367
780
|
class RTVIBotStartedSpeakingMessage(BaseModel):
|
|
781
|
+
"""Message indicating bot has started speaking."""
|
|
782
|
+
|
|
368
783
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
369
784
|
type: Literal["bot-started-speaking"] = "bot-started-speaking"
|
|
370
785
|
|
|
371
786
|
|
|
372
787
|
class RTVIBotStoppedSpeakingMessage(BaseModel):
|
|
788
|
+
"""Message indicating bot has stopped speaking."""
|
|
789
|
+
|
|
373
790
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
374
791
|
type: Literal["bot-stopped-speaking"] = "bot-stopped-speaking"
|
|
375
792
|
|
|
376
793
|
|
|
377
794
|
class RTVIMetricsMessage(BaseModel):
|
|
795
|
+
"""Message containing performance metrics.
|
|
796
|
+
|
|
797
|
+
Sent to provide performance and usage metrics.
|
|
798
|
+
"""
|
|
799
|
+
|
|
378
800
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
379
801
|
type: Literal["metrics"] = "metrics"
|
|
380
802
|
data: Mapping[str, Any]
|
|
381
803
|
|
|
382
804
|
|
|
383
805
|
class RTVIServerMessage(BaseModel):
|
|
806
|
+
"""Generic server message.
|
|
807
|
+
|
|
808
|
+
Used for custom server-to-client messages.
|
|
809
|
+
"""
|
|
810
|
+
|
|
384
811
|
label: RTVIMessageLiteral = RTVI_MESSAGE_LABEL
|
|
385
812
|
type: Literal["server-message"] = "server-message"
|
|
386
813
|
data: Any
|
|
@@ -388,28 +815,32 @@ class RTVIServerMessage(BaseModel):
|
|
|
388
815
|
|
|
389
816
|
@dataclass
|
|
390
817
|
class RTVIServerMessageFrame(SystemFrame):
|
|
391
|
-
"""A frame for sending server messages to the client.
|
|
818
|
+
"""A frame for sending server messages to the client.
|
|
819
|
+
|
|
820
|
+
Parameters:
|
|
821
|
+
data: The message data to send to the client.
|
|
822
|
+
"""
|
|
392
823
|
|
|
393
824
|
data: Any
|
|
394
825
|
|
|
395
826
|
def __str__(self):
|
|
827
|
+
"""String representation of the RTVI server message frame."""
|
|
396
828
|
return f"{self.name}(data: {self.data})"
|
|
397
829
|
|
|
398
830
|
|
|
399
831
|
@dataclass
|
|
400
832
|
class RTVIObserverParams:
|
|
401
|
-
"""
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
errors_enabled (bool): Indicates if errors messages should be sent.
|
|
833
|
+
"""Parameters for configuring RTVI Observer behavior.
|
|
834
|
+
|
|
835
|
+
Parameters:
|
|
836
|
+
bot_llm_enabled: Indicates if the bot's LLM messages should be sent.
|
|
837
|
+
bot_tts_enabled: Indicates if the bot's TTS messages should be sent.
|
|
838
|
+
bot_speaking_enabled: Indicates if the bot's started/stopped speaking messages should be sent.
|
|
839
|
+
user_llm_enabled: Indicates if the user's LLM input messages should be sent.
|
|
840
|
+
user_speaking_enabled: Indicates if the user's started/stopped speaking messages should be sent.
|
|
841
|
+
user_transcription_enabled: Indicates if user's transcription messages should be sent.
|
|
842
|
+
metrics_enabled: Indicates if metrics messages should be sent.
|
|
843
|
+
errors_enabled: Indicates if errors messages should be sent.
|
|
413
844
|
"""
|
|
414
845
|
|
|
415
846
|
bot_llm_enabled: bool = True
|
|
@@ -432,15 +863,18 @@ class RTVIObserver(BaseObserver):
|
|
|
432
863
|
Note:
|
|
433
864
|
This observer only handles outgoing messages. Incoming RTVI client messages
|
|
434
865
|
are handled by the RTVIProcessor.
|
|
435
|
-
|
|
436
|
-
Args:
|
|
437
|
-
rtvi (RTVIProcessor): The RTVI processor to push frames to.
|
|
438
|
-
params (RTVIObserverParams): Settings to enable/disable specific messages.
|
|
439
866
|
"""
|
|
440
867
|
|
|
441
868
|
def __init__(
|
|
442
869
|
self, rtvi: "RTVIProcessor", *, params: Optional[RTVIObserverParams] = None, **kwargs
|
|
443
870
|
):
|
|
871
|
+
"""Initialize the RTVI observer.
|
|
872
|
+
|
|
873
|
+
Args:
|
|
874
|
+
rtvi: The RTVI processor to push frames to.
|
|
875
|
+
params: Settings to enable/disable specific messages.
|
|
876
|
+
**kwargs: Additional arguments passed to parent class.
|
|
877
|
+
"""
|
|
444
878
|
super().__init__(**kwargs)
|
|
445
879
|
self._rtvi = rtvi
|
|
446
880
|
self._params = params or RTVIObserverParams()
|
|
@@ -452,11 +886,7 @@ class RTVIObserver(BaseObserver):
|
|
|
452
886
|
"""Process a frame being pushed through the pipeline.
|
|
453
887
|
|
|
454
888
|
Args:
|
|
455
|
-
|
|
456
|
-
dst: Destination processor receiving the frame
|
|
457
|
-
frame: The frame being pushed
|
|
458
|
-
direction: Direction of frame flow in pipeline
|
|
459
|
-
timestamp: Time when frame was pushed
|
|
889
|
+
data: Frame push event data containing source, frame, direction, and timestamp.
|
|
460
890
|
"""
|
|
461
891
|
src = data.source
|
|
462
892
|
frame = data.frame
|
|
@@ -509,6 +939,11 @@ class RTVIObserver(BaseObserver):
|
|
|
509
939
|
elif isinstance(frame, RTVIServerMessageFrame):
|
|
510
940
|
message = RTVIServerMessage(data=frame.data)
|
|
511
941
|
await self.push_transport_message_urgent(message)
|
|
942
|
+
elif isinstance(frame, RTVIServerResponseFrame):
|
|
943
|
+
if frame.error is not None:
|
|
944
|
+
await self._send_error_response(frame)
|
|
945
|
+
else:
|
|
946
|
+
await self._send_server_response(frame)
|
|
512
947
|
|
|
513
948
|
if mark_as_seen:
|
|
514
949
|
self._frames_seen.add(frame.id)
|
|
@@ -517,13 +952,14 @@ class RTVIObserver(BaseObserver):
|
|
|
517
952
|
"""Push an urgent transport message to the RTVI processor.
|
|
518
953
|
|
|
519
954
|
Args:
|
|
520
|
-
model: The message model to send
|
|
521
|
-
exclude_none: Whether to exclude None values from the model dump
|
|
955
|
+
model: The message model to send.
|
|
956
|
+
exclude_none: Whether to exclude None values from the model dump.
|
|
522
957
|
"""
|
|
523
958
|
frame = TransportMessageUrgentFrame(message=model.model_dump(exclude_none=exclude_none))
|
|
524
959
|
await self._rtvi.push_frame(frame)
|
|
525
960
|
|
|
526
961
|
async def _push_bot_transcription(self):
|
|
962
|
+
"""Push accumulated bot transcription as a message."""
|
|
527
963
|
if len(self._bot_transcription) > 0:
|
|
528
964
|
message = RTVIBotTranscriptionMessage(
|
|
529
965
|
data=RTVITextMessageData(text=self._bot_transcription)
|
|
@@ -532,6 +968,7 @@ class RTVIObserver(BaseObserver):
|
|
|
532
968
|
self._bot_transcription = ""
|
|
533
969
|
|
|
534
970
|
async def _handle_interruptions(self, frame: Frame):
|
|
971
|
+
"""Handle user speaking interruption frames."""
|
|
535
972
|
message = None
|
|
536
973
|
if isinstance(frame, UserStartedSpeakingFrame):
|
|
537
974
|
message = RTVIUserStartedSpeakingMessage()
|
|
@@ -542,6 +979,7 @@ class RTVIObserver(BaseObserver):
|
|
|
542
979
|
await self.push_transport_message_urgent(message)
|
|
543
980
|
|
|
544
981
|
async def _handle_bot_speaking(self, frame: Frame):
|
|
982
|
+
"""Handle bot speaking event frames."""
|
|
545
983
|
message = None
|
|
546
984
|
if isinstance(frame, BotStartedSpeakingFrame):
|
|
547
985
|
message = RTVIBotStartedSpeakingMessage()
|
|
@@ -552,6 +990,7 @@ class RTVIObserver(BaseObserver):
|
|
|
552
990
|
await self.push_transport_message_urgent(message)
|
|
553
991
|
|
|
554
992
|
async def _handle_llm_text_frame(self, frame: LLMTextFrame):
|
|
993
|
+
"""Handle LLM text output frames."""
|
|
555
994
|
message = RTVIBotLLMTextMessage(data=RTVITextMessageData(text=frame.text))
|
|
556
995
|
await self.push_transport_message_urgent(message)
|
|
557
996
|
|
|
@@ -560,6 +999,7 @@ class RTVIObserver(BaseObserver):
|
|
|
560
999
|
await self._push_bot_transcription()
|
|
561
1000
|
|
|
562
1001
|
async def _handle_user_transcriptions(self, frame: Frame):
|
|
1002
|
+
"""Handle user transcription frames."""
|
|
563
1003
|
message = None
|
|
564
1004
|
if isinstance(frame, TranscriptionFrame):
|
|
565
1005
|
message = RTVIUserTranscriptionMessage(
|
|
@@ -608,6 +1048,7 @@ class RTVIObserver(BaseObserver):
|
|
|
608
1048
|
logger.warning(f"Caught an error while trying to handle context: {e}")
|
|
609
1049
|
|
|
610
1050
|
async def _handle_metrics(self, frame: MetricsFrame):
|
|
1051
|
+
"""Handle metrics frames and convert to RTVI metrics messages."""
|
|
611
1052
|
metrics = {}
|
|
612
1053
|
for d in frame.data:
|
|
613
1054
|
if isinstance(d, TTFBMetricsData):
|
|
@@ -630,8 +1071,31 @@ class RTVIObserver(BaseObserver):
|
|
|
630
1071
|
message = RTVIMetricsMessage(data=metrics)
|
|
631
1072
|
await self.push_transport_message_urgent(message)
|
|
632
1073
|
|
|
1074
|
+
async def _send_server_response(self, frame: RTVIServerResponseFrame):
|
|
1075
|
+
"""Send a response to the client for a specific request."""
|
|
1076
|
+
message = RTVIServerResponse(
|
|
1077
|
+
id=str(frame.client_msg.msg_id),
|
|
1078
|
+
data=RTVIRawServerResponseData(t=frame.client_msg.type, d=frame.data),
|
|
1079
|
+
)
|
|
1080
|
+
await self.push_transport_message_urgent(message)
|
|
1081
|
+
|
|
1082
|
+
async def _send_error_response(self, frame: RTVIServerResponseFrame):
|
|
1083
|
+
"""Send a response to the client for a specific request."""
|
|
1084
|
+
if self._params.errors_enabled:
|
|
1085
|
+
message = RTVIErrorResponse(
|
|
1086
|
+
id=str(frame.client_msg.msg_id), data=RTVIErrorResponseData(error=frame.error)
|
|
1087
|
+
)
|
|
1088
|
+
await self.push_transport_message_urgent(message)
|
|
1089
|
+
|
|
633
1090
|
|
|
634
1091
|
class RTVIProcessor(FrameProcessor):
|
|
1092
|
+
"""Main processor for handling RTVI protocol messages and actions.
|
|
1093
|
+
|
|
1094
|
+
This processor manages the RTVI protocol communication including client-server
|
|
1095
|
+
handshaking, configuration management, action execution, and message routing.
|
|
1096
|
+
It serves as the central hub for RTVI protocol operations.
|
|
1097
|
+
"""
|
|
1098
|
+
|
|
635
1099
|
def __init__(
|
|
636
1100
|
self,
|
|
637
1101
|
*,
|
|
@@ -639,12 +1103,20 @@ class RTVIProcessor(FrameProcessor):
|
|
|
639
1103
|
transport: Optional[BaseTransport] = None,
|
|
640
1104
|
**kwargs,
|
|
641
1105
|
):
|
|
1106
|
+
"""Initialize the RTVI processor.
|
|
1107
|
+
|
|
1108
|
+
Args:
|
|
1109
|
+
config: Initial RTVI configuration.
|
|
1110
|
+
transport: Transport layer for communication.
|
|
1111
|
+
**kwargs: Additional arguments passed to parent class.
|
|
1112
|
+
"""
|
|
642
1113
|
super().__init__(**kwargs)
|
|
643
1114
|
self._config = config or RTVIConfig(config=[])
|
|
644
1115
|
|
|
645
1116
|
self._bot_ready = False
|
|
646
1117
|
self._client_ready = False
|
|
647
1118
|
self._client_ready_id = ""
|
|
1119
|
+
self._client_version = []
|
|
648
1120
|
self._errors_enabled = True
|
|
649
1121
|
|
|
650
1122
|
self._registered_actions: Dict[str, RTVIAction] = {}
|
|
@@ -658,6 +1130,7 @@ class RTVIProcessor(FrameProcessor):
|
|
|
658
1130
|
|
|
659
1131
|
self._register_event_handler("on_bot_started")
|
|
660
1132
|
self._register_event_handler("on_client_ready")
|
|
1133
|
+
self._register_event_handler("on_client_message")
|
|
661
1134
|
|
|
662
1135
|
self._input_transport = None
|
|
663
1136
|
self._transport = transport
|
|
@@ -668,34 +1141,101 @@ class RTVIProcessor(FrameProcessor):
|
|
|
668
1141
|
self._input_transport.enable_audio_in_stream_on_start(False)
|
|
669
1142
|
|
|
670
1143
|
def register_action(self, action: RTVIAction):
|
|
1144
|
+
"""Register an action that can be executed via RTVI.
|
|
1145
|
+
|
|
1146
|
+
Args:
|
|
1147
|
+
action: The action to register.
|
|
1148
|
+
"""
|
|
1149
|
+
import warnings
|
|
1150
|
+
|
|
1151
|
+
with warnings.catch_warnings():
|
|
1152
|
+
warnings.simplefilter("always")
|
|
1153
|
+
warnings.warn(
|
|
1154
|
+
"The actions API is deprecated, use server and client messages instead.",
|
|
1155
|
+
DeprecationWarning,
|
|
1156
|
+
)
|
|
1157
|
+
|
|
671
1158
|
id = self._action_id(action.service, action.action)
|
|
672
1159
|
self._registered_actions[id] = action
|
|
673
1160
|
|
|
674
1161
|
def register_service(self, service: RTVIService):
|
|
1162
|
+
"""Register a service that can be configured via RTVI.
|
|
1163
|
+
|
|
1164
|
+
Args:
|
|
1165
|
+
service: The service to register.
|
|
1166
|
+
"""
|
|
1167
|
+
import warnings
|
|
1168
|
+
|
|
1169
|
+
with warnings.catch_warnings():
|
|
1170
|
+
warnings.simplefilter("always")
|
|
1171
|
+
warnings.warn(
|
|
1172
|
+
"The actions API is deprecated, use server and client messages instead.",
|
|
1173
|
+
DeprecationWarning,
|
|
1174
|
+
)
|
|
1175
|
+
|
|
675
1176
|
self._registered_services[service.name] = service
|
|
676
1177
|
|
|
677
1178
|
async def set_client_ready(self):
|
|
1179
|
+
"""Mark the client as ready and trigger the ready event."""
|
|
678
1180
|
self._client_ready = True
|
|
679
1181
|
await self._call_event_handler("on_client_ready")
|
|
680
1182
|
|
|
681
1183
|
async def set_bot_ready(self):
|
|
1184
|
+
"""Mark the bot as ready and send the bot-ready message."""
|
|
682
1185
|
self._bot_ready = True
|
|
683
1186
|
await self._update_config(self._config, False)
|
|
684
1187
|
await self._send_bot_ready()
|
|
685
1188
|
|
|
686
1189
|
def set_errors_enabled(self, enabled: bool):
|
|
1190
|
+
"""Enable or disable error message sending.
|
|
1191
|
+
|
|
1192
|
+
Args:
|
|
1193
|
+
enabled: Whether to send error messages.
|
|
1194
|
+
"""
|
|
687
1195
|
self._errors_enabled = enabled
|
|
688
1196
|
|
|
689
1197
|
async def interrupt_bot(self):
|
|
1198
|
+
"""Send a bot interruption frame upstream."""
|
|
690
1199
|
await self.push_frame(BotInterruptionFrame(), FrameDirection.UPSTREAM)
|
|
691
1200
|
|
|
1201
|
+
async def send_server_message(self, data: Any):
|
|
1202
|
+
"""Send a server message to the client."""
|
|
1203
|
+
message = RTVIServerMessage(data=data)
|
|
1204
|
+
await self._send_server_message(message)
|
|
1205
|
+
|
|
1206
|
+
async def send_server_response(self, client_msg: RTVIClientMessage, data: Any):
|
|
1207
|
+
"""Send a server response for a given client message."""
|
|
1208
|
+
message = RTVIServerResponse(
|
|
1209
|
+
id=client_msg.msg_id, data=RTVIRawServerResponseData(t=client_msg.type, d=data)
|
|
1210
|
+
)
|
|
1211
|
+
await self._send_server_message(message)
|
|
1212
|
+
|
|
1213
|
+
async def send_error_response(self, client_msg: RTVIClientMessage, error: str):
|
|
1214
|
+
"""Send an error response for a given client message."""
|
|
1215
|
+
await self._send_error_response(id=client_msg.msg_id, error=error)
|
|
1216
|
+
|
|
692
1217
|
async def send_error(self, error: str):
|
|
1218
|
+
"""Send an error message to the client.
|
|
1219
|
+
|
|
1220
|
+
Args:
|
|
1221
|
+
error: The error message to send.
|
|
1222
|
+
"""
|
|
693
1223
|
await self._send_error_frame(ErrorFrame(error=error))
|
|
694
1224
|
|
|
695
1225
|
async def handle_message(self, message: RTVIMessage):
|
|
1226
|
+
"""Handle an incoming RTVI message.
|
|
1227
|
+
|
|
1228
|
+
Args:
|
|
1229
|
+
message: The RTVI message to handle.
|
|
1230
|
+
"""
|
|
696
1231
|
await self._message_queue.put(message)
|
|
697
1232
|
|
|
698
1233
|
async def handle_function_call(self, params: FunctionCallParams):
|
|
1234
|
+
"""Handle a function call from the LLM.
|
|
1235
|
+
|
|
1236
|
+
Args:
|
|
1237
|
+
params: The function call parameters.
|
|
1238
|
+
"""
|
|
699
1239
|
fn = RTVILLMFunctionCallMessageData(
|
|
700
1240
|
function_name=params.function_name,
|
|
701
1241
|
tool_call_id=params.tool_call_id,
|
|
@@ -707,6 +1247,17 @@ class RTVIProcessor(FrameProcessor):
|
|
|
707
1247
|
async def handle_function_call_start(
|
|
708
1248
|
self, function_name: str, llm: FrameProcessor, context: OpenAILLMContext
|
|
709
1249
|
):
|
|
1250
|
+
"""Handle the start of a function call from the LLM.
|
|
1251
|
+
|
|
1252
|
+
.. deprecated:: 0.0.66
|
|
1253
|
+
This method is deprecated and will be removed in a future version.
|
|
1254
|
+
Use `RTVIProcessor.handle_function_call()` instead.
|
|
1255
|
+
|
|
1256
|
+
Args:
|
|
1257
|
+
function_name: Name of the function being called.
|
|
1258
|
+
llm: The LLM processor making the call.
|
|
1259
|
+
context: The LLM context.
|
|
1260
|
+
"""
|
|
710
1261
|
import warnings
|
|
711
1262
|
|
|
712
1263
|
with warnings.catch_warnings():
|
|
@@ -721,6 +1272,12 @@ class RTVIProcessor(FrameProcessor):
|
|
|
721
1272
|
await self._push_transport_message(message, exclude_none=False)
|
|
722
1273
|
|
|
723
1274
|
async def process_frame(self, frame: Frame, direction: FrameDirection):
|
|
1275
|
+
"""Process incoming frames through the RTVI processor.
|
|
1276
|
+
|
|
1277
|
+
Args:
|
|
1278
|
+
frame: The frame to process.
|
|
1279
|
+
direction: The direction of frame flow.
|
|
1280
|
+
"""
|
|
724
1281
|
await super().process_frame(frame, direction)
|
|
725
1282
|
|
|
726
1283
|
# Specific system frames
|
|
@@ -754,21 +1311,25 @@ class RTVIProcessor(FrameProcessor):
|
|
|
754
1311
|
await self.push_frame(frame, direction)
|
|
755
1312
|
|
|
756
1313
|
async def _start(self, frame: StartFrame):
|
|
1314
|
+
"""Start the RTVI processor tasks."""
|
|
757
1315
|
if not self._action_task:
|
|
758
|
-
self._action_queue =
|
|
1316
|
+
self._action_queue = asyncio.Queue()
|
|
759
1317
|
self._action_task = self.create_task(self._action_task_handler())
|
|
760
1318
|
if not self._message_task:
|
|
761
|
-
self._message_queue =
|
|
1319
|
+
self._message_queue = asyncio.Queue()
|
|
762
1320
|
self._message_task = self.create_task(self._message_task_handler())
|
|
763
1321
|
await self._call_event_handler("on_bot_started")
|
|
764
1322
|
|
|
765
1323
|
async def _stop(self, frame: EndFrame):
|
|
1324
|
+
"""Stop the RTVI processor tasks."""
|
|
766
1325
|
await self._cancel_tasks()
|
|
767
1326
|
|
|
768
1327
|
async def _cancel(self, frame: CancelFrame):
|
|
1328
|
+
"""Cancel the RTVI processor tasks."""
|
|
769
1329
|
await self._cancel_tasks()
|
|
770
1330
|
|
|
771
1331
|
async def _cancel_tasks(self):
|
|
1332
|
+
"""Cancel all running tasks."""
|
|
772
1333
|
if self._action_task:
|
|
773
1334
|
await self.cancel_task(self._action_task)
|
|
774
1335
|
self._action_task = None
|
|
@@ -778,22 +1339,26 @@ class RTVIProcessor(FrameProcessor):
|
|
|
778
1339
|
self._message_task = None
|
|
779
1340
|
|
|
780
1341
|
async def _push_transport_message(self, model: BaseModel, exclude_none: bool = True):
|
|
1342
|
+
"""Push a transport message frame."""
|
|
781
1343
|
frame = TransportMessageUrgentFrame(message=model.model_dump(exclude_none=exclude_none))
|
|
782
1344
|
await self.push_frame(frame)
|
|
783
1345
|
|
|
784
1346
|
async def _action_task_handler(self):
|
|
1347
|
+
"""Handle incoming action frames."""
|
|
785
1348
|
while True:
|
|
786
1349
|
frame = await self._action_queue.get()
|
|
787
1350
|
await self._handle_action(frame.message_id, frame.rtvi_action_run)
|
|
788
1351
|
self._action_queue.task_done()
|
|
789
1352
|
|
|
790
1353
|
async def _message_task_handler(self):
|
|
1354
|
+
"""Handle incoming transport messages."""
|
|
791
1355
|
while True:
|
|
792
1356
|
message = await self._message_queue.get()
|
|
793
1357
|
await self._handle_message(message)
|
|
794
1358
|
self._message_queue.task_done()
|
|
795
1359
|
|
|
796
1360
|
async def _handle_transport_message(self, frame: TransportMessageUrgentFrame):
|
|
1361
|
+
"""Handle an incoming transport message frame."""
|
|
797
1362
|
try:
|
|
798
1363
|
transport_message = frame.message
|
|
799
1364
|
if transport_message.get("label") != RTVI_MESSAGE_LABEL:
|
|
@@ -806,10 +1371,19 @@ class RTVIProcessor(FrameProcessor):
|
|
|
806
1371
|
logger.warning(f"Invalid RTVI transport message: {e}")
|
|
807
1372
|
|
|
808
1373
|
async def _handle_message(self, message: RTVIMessage):
|
|
1374
|
+
"""Handle a parsed RTVI message."""
|
|
809
1375
|
try:
|
|
810
1376
|
match message.type:
|
|
811
1377
|
case "client-ready":
|
|
812
|
-
|
|
1378
|
+
data = None
|
|
1379
|
+
try:
|
|
1380
|
+
data = RTVIClientReadyData.model_validate(message.data)
|
|
1381
|
+
except ValidationError:
|
|
1382
|
+
# Not all clients have been updated to RTVI 1.0.0.
|
|
1383
|
+
# For now, that's okay, we just log their info as unknown.
|
|
1384
|
+
data = None
|
|
1385
|
+
pass
|
|
1386
|
+
await self._handle_client_ready(message.id, data)
|
|
813
1387
|
case "describe-actions":
|
|
814
1388
|
await self._handle_describe_actions(message.id)
|
|
815
1389
|
case "describe-config":
|
|
@@ -821,6 +1395,9 @@ class RTVIProcessor(FrameProcessor):
|
|
|
821
1395
|
await self._handle_update_config(message.id, update_config)
|
|
822
1396
|
case "disconnect-bot":
|
|
823
1397
|
await self.push_frame(EndTaskFrame(), FrameDirection.UPSTREAM)
|
|
1398
|
+
case "client-message":
|
|
1399
|
+
data = RTVIRawClientMessageData.model_validate(message.data)
|
|
1400
|
+
await self._handle_client_message(message.id, data)
|
|
824
1401
|
case "action":
|
|
825
1402
|
action = RTVIActionRun.model_validate(message.data)
|
|
826
1403
|
action_frame = RTVIActionFrame(message_id=message.id, rtvi_action_run=action)
|
|
@@ -828,6 +1405,9 @@ class RTVIProcessor(FrameProcessor):
|
|
|
828
1405
|
case "llm-function-call-result":
|
|
829
1406
|
data = RTVILLMFunctionCallResultData.model_validate(message.data)
|
|
830
1407
|
await self._handle_function_call_result(data)
|
|
1408
|
+
case "append-to-context":
|
|
1409
|
+
data = RTVIAppendToContextData.model_validate(message.data)
|
|
1410
|
+
await self._handle_update_context(data)
|
|
831
1411
|
case "raw-audio" | "raw-audio-batch":
|
|
832
1412
|
await self._handle_audio_buffer(message.data)
|
|
833
1413
|
|
|
@@ -841,8 +1421,20 @@ class RTVIProcessor(FrameProcessor):
|
|
|
841
1421
|
await self._send_error_response(message.id, f"Exception processing message: {e}")
|
|
842
1422
|
logger.warning(f"Exception processing message: {e}")
|
|
843
1423
|
|
|
844
|
-
async def _handle_client_ready(self, request_id: str):
|
|
845
|
-
|
|
1424
|
+
async def _handle_client_ready(self, request_id: str, data: RTVIClientReadyData | None):
|
|
1425
|
+
"""Handle the client-ready message from the client."""
|
|
1426
|
+
version = data.version if data else "unknown"
|
|
1427
|
+
logger.debug(f"Received client-ready: version {version}")
|
|
1428
|
+
if version == "unknown":
|
|
1429
|
+
self._client_version = [0, 3, 0] # Default to 0.3.0 if unknown
|
|
1430
|
+
else:
|
|
1431
|
+
try:
|
|
1432
|
+
self._client_version = [int(v) for v in version.split(".")]
|
|
1433
|
+
except ValueError:
|
|
1434
|
+
logger.warning(f"Invalid client version format: {version}")
|
|
1435
|
+
self._client_version = [0, 3, 0]
|
|
1436
|
+
about = data.about if data else {"library": "unknown"}
|
|
1437
|
+
logger.debug(f"Client Details: {about}")
|
|
846
1438
|
if self._input_transport:
|
|
847
1439
|
await self._input_transport.start_audio_in_streaming()
|
|
848
1440
|
|
|
@@ -850,6 +1442,7 @@ class RTVIProcessor(FrameProcessor):
|
|
|
850
1442
|
await self.set_client_ready()
|
|
851
1443
|
|
|
852
1444
|
async def _handle_audio_buffer(self, data):
|
|
1445
|
+
"""Handle incoming audio buffer data."""
|
|
853
1446
|
if not self._input_transport:
|
|
854
1447
|
return
|
|
855
1448
|
|
|
@@ -871,20 +1464,51 @@ class RTVIProcessor(FrameProcessor):
|
|
|
871
1464
|
logger.error(f"Error processing audio buffer: {e}")
|
|
872
1465
|
|
|
873
1466
|
async def _handle_describe_config(self, request_id: str):
|
|
1467
|
+
"""Handle a describe-config request."""
|
|
1468
|
+
import warnings
|
|
1469
|
+
|
|
1470
|
+
with warnings.catch_warnings():
|
|
1471
|
+
warnings.simplefilter("always")
|
|
1472
|
+
warnings.warn(
|
|
1473
|
+
"Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.",
|
|
1474
|
+
DeprecationWarning,
|
|
1475
|
+
)
|
|
1476
|
+
|
|
874
1477
|
services = list(self._registered_services.values())
|
|
875
1478
|
message = RTVIDescribeConfig(id=request_id, data=RTVIDescribeConfigData(config=services))
|
|
876
1479
|
await self._push_transport_message(message)
|
|
877
1480
|
|
|
878
1481
|
async def _handle_describe_actions(self, request_id: str):
|
|
1482
|
+
"""Handle a describe-actions request."""
|
|
1483
|
+
import warnings
|
|
1484
|
+
|
|
1485
|
+
with warnings.catch_warnings():
|
|
1486
|
+
warnings.simplefilter("always")
|
|
1487
|
+
warnings.warn(
|
|
1488
|
+
"The Actions API is deprecated, use custom server and client messages instead.",
|
|
1489
|
+
DeprecationWarning,
|
|
1490
|
+
)
|
|
1491
|
+
|
|
879
1492
|
actions = list(self._registered_actions.values())
|
|
880
1493
|
message = RTVIDescribeActions(id=request_id, data=RTVIDescribeActionsData(actions=actions))
|
|
881
1494
|
await self._push_transport_message(message)
|
|
882
1495
|
|
|
883
1496
|
async def _handle_get_config(self, request_id: str):
|
|
1497
|
+
"""Handle a get-config request."""
|
|
1498
|
+
import warnings
|
|
1499
|
+
|
|
1500
|
+
with warnings.catch_warnings():
|
|
1501
|
+
warnings.simplefilter("always")
|
|
1502
|
+
warnings.warn(
|
|
1503
|
+
"Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.",
|
|
1504
|
+
DeprecationWarning,
|
|
1505
|
+
)
|
|
1506
|
+
|
|
884
1507
|
message = RTVIConfigResponse(id=request_id, data=self._config)
|
|
885
1508
|
await self._push_transport_message(message)
|
|
886
1509
|
|
|
887
1510
|
def _update_config_option(self, service: str, config: RTVIServiceOptionConfig):
|
|
1511
|
+
"""Update a specific configuration option."""
|
|
888
1512
|
for service_config in self._config.config:
|
|
889
1513
|
if service_config.service == service:
|
|
890
1514
|
for option_config in service_config.options:
|
|
@@ -896,6 +1520,16 @@ class RTVIProcessor(FrameProcessor):
|
|
|
896
1520
|
service_config.options.append(config)
|
|
897
1521
|
|
|
898
1522
|
async def _update_service_config(self, config: RTVIServiceConfig):
|
|
1523
|
+
"""Update configuration for a specific service."""
|
|
1524
|
+
import warnings
|
|
1525
|
+
|
|
1526
|
+
with warnings.catch_warnings():
|
|
1527
|
+
warnings.simplefilter("always")
|
|
1528
|
+
warnings.warn(
|
|
1529
|
+
"Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.",
|
|
1530
|
+
DeprecationWarning,
|
|
1531
|
+
)
|
|
1532
|
+
|
|
899
1533
|
service = self._registered_services[config.service]
|
|
900
1534
|
for option in config.options:
|
|
901
1535
|
handler = service._options_dict[option.name].handler
|
|
@@ -903,16 +1537,55 @@ class RTVIProcessor(FrameProcessor):
|
|
|
903
1537
|
self._update_config_option(service.name, option)
|
|
904
1538
|
|
|
905
1539
|
async def _update_config(self, data: RTVIConfig, interrupt: bool):
|
|
1540
|
+
"""Update the RTVI configuration."""
|
|
1541
|
+
import warnings
|
|
1542
|
+
|
|
1543
|
+
with warnings.catch_warnings():
|
|
1544
|
+
warnings.simplefilter("always")
|
|
1545
|
+
warnings.warn(
|
|
1546
|
+
"Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.",
|
|
1547
|
+
DeprecationWarning,
|
|
1548
|
+
)
|
|
1549
|
+
|
|
906
1550
|
if interrupt:
|
|
907
1551
|
await self.interrupt_bot()
|
|
908
1552
|
for service_config in data.config:
|
|
909
1553
|
await self._update_service_config(service_config)
|
|
910
1554
|
|
|
911
1555
|
async def _handle_update_config(self, request_id: str, data: RTVIUpdateConfig):
|
|
1556
|
+
"""Handle an update-config request."""
|
|
912
1557
|
await self._update_config(RTVIConfig(config=data.config), data.interrupt)
|
|
913
1558
|
await self._handle_get_config(request_id)
|
|
914
1559
|
|
|
1560
|
+
async def _handle_update_context(self, data: RTVIAppendToContextData):
|
|
1561
|
+
if data.run_immediately:
|
|
1562
|
+
await self.interrupt_bot()
|
|
1563
|
+
frame = LLMMessagesAppendFrame(
|
|
1564
|
+
messages=[{"role": data.role, "content": data.content}],
|
|
1565
|
+
run_llm=data.run_immediately,
|
|
1566
|
+
)
|
|
1567
|
+
await self.push_frame(frame)
|
|
1568
|
+
|
|
1569
|
+
async def _handle_client_message(self, msg_id: str, data: RTVIRawClientMessageData):
|
|
1570
|
+
"""Handle a client message frame."""
|
|
1571
|
+
if not data:
|
|
1572
|
+
await self._send_error_response(msg_id, "Malformed client message")
|
|
1573
|
+
return
|
|
1574
|
+
|
|
1575
|
+
# Create a RTVIClientMessageFrame to push the message
|
|
1576
|
+
frame = RTVIClientMessageFrame(msg_id=msg_id, type=data.t, data=data.d)
|
|
1577
|
+
await self.push_frame(frame)
|
|
1578
|
+
await self._call_event_handler(
|
|
1579
|
+
"on_client_message",
|
|
1580
|
+
RTVIClientMessage(
|
|
1581
|
+
msg_id=msg_id,
|
|
1582
|
+
type=data.t,
|
|
1583
|
+
data=data.d,
|
|
1584
|
+
),
|
|
1585
|
+
)
|
|
1586
|
+
|
|
915
1587
|
async def _handle_function_call_result(self, data):
|
|
1588
|
+
"""Handle a function call result from the client."""
|
|
916
1589
|
frame = FunctionCallResultFrame(
|
|
917
1590
|
function_name=data.function_name,
|
|
918
1591
|
tool_call_id=data.tool_call_id,
|
|
@@ -922,6 +1595,7 @@ class RTVIProcessor(FrameProcessor):
|
|
|
922
1595
|
await self.push_frame(frame)
|
|
923
1596
|
|
|
924
1597
|
async def _handle_action(self, request_id: Optional[str], data: RTVIActionRun):
|
|
1598
|
+
"""Handle an action execution request."""
|
|
925
1599
|
action_id = self._action_id(data.service, data.action)
|
|
926
1600
|
if action_id not in self._registered_actions:
|
|
927
1601
|
await self._send_error_response(request_id, f"Action {action_id} not registered")
|
|
@@ -939,21 +1613,32 @@ class RTVIProcessor(FrameProcessor):
|
|
|
939
1613
|
await self._push_transport_message(message)
|
|
940
1614
|
|
|
941
1615
|
async def _send_bot_ready(self):
|
|
1616
|
+
"""Send the bot-ready message to the client."""
|
|
1617
|
+
config = None
|
|
1618
|
+
if self._client_version[0] < 1:
|
|
1619
|
+
config = self._config.config
|
|
942
1620
|
message = RTVIBotReady(
|
|
943
1621
|
id=self._client_ready_id,
|
|
944
|
-
data=RTVIBotReadyData(version=RTVI_PROTOCOL_VERSION, config=
|
|
1622
|
+
data=RTVIBotReadyData(version=RTVI_PROTOCOL_VERSION, config=config),
|
|
945
1623
|
)
|
|
946
1624
|
await self._push_transport_message(message)
|
|
947
1625
|
|
|
1626
|
+
async def _send_server_message(self, message: RTVIServerMessage | RTVIServerResponse):
|
|
1627
|
+
"""Send a message or response to the client."""
|
|
1628
|
+
await self._push_transport_message(message)
|
|
1629
|
+
|
|
948
1630
|
async def _send_error_frame(self, frame: ErrorFrame):
|
|
1631
|
+
"""Send an error frame as an RTVI error message."""
|
|
949
1632
|
if self._errors_enabled:
|
|
950
1633
|
message = RTVIError(data=RTVIErrorData(error=frame.error, fatal=frame.fatal))
|
|
951
1634
|
await self._push_transport_message(message)
|
|
952
1635
|
|
|
953
1636
|
async def _send_error_response(self, id: str, error: str):
|
|
1637
|
+
"""Send an error response message."""
|
|
954
1638
|
if self._errors_enabled:
|
|
955
1639
|
message = RTVIErrorResponse(id=id, data=RTVIErrorResponseData(error=error))
|
|
956
1640
|
await self._push_transport_message(message)
|
|
957
1641
|
|
|
958
1642
|
def _action_id(self, service: str, action: str) -> str:
|
|
1643
|
+
"""Generate an action ID from service and action names."""
|
|
959
1644
|
return f"{service}:{action}"
|