Add optional service field to ServiceUpdateSettingsFrame for targeting a specific service instance
When `service` is set and doesn't match, the service forwards the frame instead of consuming it. This allows targeting a specific service when multiple services of the same type exist in the pipeline.
This commit is contained in:
@@ -2154,10 +2154,15 @@ class ServiceUpdateSettingsFrame(ControlFrame, UninterruptibleFrame):
|
|||||||
|
|
||||||
delta: :class:`~pipecat.services.settings.ServiceSettings` delta-mode
|
delta: :class:`~pipecat.services.settings.ServiceSettings` delta-mode
|
||||||
object describing the fields to change.
|
object describing the fields to change.
|
||||||
|
|
||||||
|
service: Optional target service instance. When provided, only that
|
||||||
|
service will apply the settings; other services will forward the
|
||||||
|
frame unchanged.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
settings: Mapping[str, Any] = field(default_factory=dict)
|
settings: Mapping[str, Any] = field(default_factory=dict)
|
||||||
delta: Optional["ServiceSettings"] = None
|
delta: Optional["ServiceSettings"] = None
|
||||||
|
service: Optional["FrameProcessor"] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -403,7 +403,9 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService):
|
|||||||
elif isinstance(frame, LLMConfigureOutputFrame):
|
elif isinstance(frame, LLMConfigureOutputFrame):
|
||||||
self._skip_tts = frame.skip_tts
|
self._skip_tts = frame.skip_tts
|
||||||
elif isinstance(frame, LLMUpdateSettingsFrame):
|
elif isinstance(frame, LLMUpdateSettingsFrame):
|
||||||
if frame.delta is not None:
|
if frame.service is not None and frame.service is not self:
|
||||||
|
await self.push_frame(frame, direction)
|
||||||
|
elif frame.delta is not None:
|
||||||
await self._update_settings(frame.delta)
|
await self._update_settings(frame.delta)
|
||||||
elif frame.settings:
|
elif frame.settings:
|
||||||
# Backward-compatible path: convert legacy dict to settings object.
|
# Backward-compatible path: convert legacy dict to settings object.
|
||||||
|
|||||||
@@ -386,7 +386,11 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
# fields, not our Settings fields, so we construct SessionProperties
|
# fields, not our Settings fields, so we construct SessionProperties
|
||||||
# directly. The frame.delta path falls through to super, which calls
|
# directly. The frame.delta path falls through to super, which calls
|
||||||
# _update_settings → our override handles the rest.
|
# _update_settings → our override handles the rest.
|
||||||
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
if (
|
||||||
|
isinstance(frame, LLMUpdateSettingsFrame)
|
||||||
|
and frame.delta is None
|
||||||
|
and (frame.service is None or frame.service is self)
|
||||||
|
):
|
||||||
self._session_properties = events.SessionProperties(**frame.settings)
|
self._session_properties = events.SessionProperties(**frame.settings)
|
||||||
await self._send_session_update()
|
await self._send_session_update()
|
||||||
await self.push_frame(frame, direction)
|
await self.push_frame(frame, direction)
|
||||||
|
|||||||
@@ -357,7 +357,9 @@ class STTService(AIService):
|
|||||||
await self._handle_vad_user_stopped_speaking(frame)
|
await self._handle_vad_user_stopped_speaking(frame)
|
||||||
await self.push_frame(frame, direction)
|
await self.push_frame(frame, direction)
|
||||||
elif isinstance(frame, STTUpdateSettingsFrame):
|
elif isinstance(frame, STTUpdateSettingsFrame):
|
||||||
if frame.delta is not None:
|
if frame.service is not None and frame.service is not self:
|
||||||
|
await self.push_frame(frame, direction)
|
||||||
|
elif frame.delta is not None:
|
||||||
await self._update_settings(frame.delta)
|
await self._update_settings(frame.delta)
|
||||||
elif frame.settings:
|
elif frame.settings:
|
||||||
# Backward-compatible path: convert legacy dict to settings object.
|
# Backward-compatible path: convert legacy dict to settings object.
|
||||||
|
|||||||
@@ -738,7 +738,9 @@ class TTSService(AIService):
|
|||||||
self._turn_context_id = saved_turn_context_id
|
self._turn_context_id = saved_turn_context_id
|
||||||
self._processing_text = processing_text
|
self._processing_text = processing_text
|
||||||
elif isinstance(frame, TTSUpdateSettingsFrame):
|
elif isinstance(frame, TTSUpdateSettingsFrame):
|
||||||
if frame.delta is not None:
|
if frame.service is not None and frame.service is not self:
|
||||||
|
await self.push_frame(frame, direction)
|
||||||
|
elif frame.delta is not None:
|
||||||
await self._update_settings(frame.delta)
|
await self._update_settings(frame.delta)
|
||||||
elif frame.settings:
|
elif frame.settings:
|
||||||
# Backward-compatible path: convert legacy dict to settings object.
|
# Backward-compatible path: convert legacy dict to settings object.
|
||||||
|
|||||||
Reference in New Issue
Block a user