LLMConfigureOutputFrame: allow configuring LLM output

This commit is contained in:
Aleix Conchillo Flaqué
2025-08-26 14:01:48 -07:00
parent 5803936838
commit 16f57be72c
4 changed files with 39 additions and 1 deletions

View File

@@ -607,6 +607,21 @@ class LLMEnablePromptCachingFrame(DataFrame):
enable: bool
@dataclass
class LLMConfigureOutputFrame(DataFrame):
"""Frame to configure LLM output.
This frame is used to configure how the LLM produces output. For example, it
can tell the LLM to generate tokens that should be added to the context but
not spoken by the TTS service (if one is present in the pipeline).
Parameters:
skip_tts: Whether LLM tokens should skip the TTS service (if any).
"""
skip_tts: bool
@dataclass
class TTSSpeakFrame(DataFrame):
"""Frame containing text that should be spoken by TTS.

View File

@@ -103,7 +103,7 @@ class DTMFAggregator(FrameProcessor):
digit_value = frame.button.value
self._aggregation += digit_value
# For first digit, schedule interruption in separate task
# For first digit, schedule interruption.
if is_first_digit:
await self.push_frame(BotInterruptionFrame(), FrameDirection.UPSTREAM)

View File

@@ -37,6 +37,8 @@ from pipecat.frames.frames import (
FunctionCallResultFrame,
FunctionCallResultProperties,
FunctionCallsStartedFrame,
LLMConfigureOutputFrame,
LLMTextFrame,
StartFrame,
StartInterruptionFrame,
UserImageRequestFrame,
@@ -179,6 +181,7 @@ class LLMService(AIService):
self._function_call_tasks: Dict[asyncio.Task, FunctionCallRunnerItem] = {}
self._sequential_runner_task: Optional[asyncio.Task] = None
self._tracing_enabled: bool = False
self._skip_tts: bool = False
self._register_event_handler("on_function_calls_started")
self._register_event_handler("on_completion_timeout")
@@ -272,6 +275,20 @@ class LLMService(AIService):
if isinstance(frame, StartInterruptionFrame):
await self._handle_interruptions(frame)
elif isinstance(frame, LLMConfigureOutputFrame):
self._skip_tts = frame.skip_tts
async def push_frame(self, frame: Frame, direction: FrameDirection = FrameDirection.DOWNSTREAM):
"""Pushes a frame.
Args:
frame: The frame to push.
direction: The direction of frame pushing.
"""
if isinstance(frame, LLMTextFrame):
frame.skip_tts = self._skip_tts
await super().push_frame(frame, direction)
async def _handle_interruptions(self, _: StartInterruptionFrame):
for function_name, entry in self._functions.items():