Remove LLMThoughtSignatureFrame in favor of using the more generic LLMMessagesAppendFrame

This commit is contained in:
Paul Kompfner
2025-12-08 11:10:05 -05:00
parent 17203ba3e6
commit 7e92597c0e
4 changed files with 18 additions and 49 deletions

View File

@@ -222,10 +222,10 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
# messages # messages
if ( if (
isinstance(message.message, dict) isinstance(message.message, dict)
and message.message.get("type") == "fn_call_thought_signature" and message.message.get("type") == "fn_thought_signature"
and (thought_signature := message.message.get("signature")) and (thought_signature := message.message.get("signature"))
): ):
self._apply_function_call_thought_signature_to_messages( self._apply_function_thought_signature_to_messages(
thought_signature, message.message.get("tool_call_id"), messages thought_signature, message.message.get("tool_call_id"), messages
) )
continue continue
@@ -234,7 +234,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
# signature messages (Gemini 3 Pro) # signature messages (Gemini 3 Pro)
if ( if (
isinstance(message.message, dict) isinstance(message.message, dict)
and message.message.get("type") == "thought_signature" and message.message.get("type") == "non_fn_thought_signature"
and (thought_signature := message.message.get("signature")) and (thought_signature := message.message.get("signature"))
): ):
non_fn_thought_signatures.append(thought_signature) non_fn_thought_signatures.append(thought_signature)
@@ -444,7 +444,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
tool_call_id_to_name_mapping=tool_call_id_to_name_mapping, tool_call_id_to_name_mapping=tool_call_id_to_name_mapping,
) )
def _apply_function_call_thought_signature_to_messages( def _apply_function_thought_signature_to_messages(
self, thought_signature: bytes, tool_call_id: str, messages: List[Content] self, thought_signature: bytes, tool_call_id: str, messages: List[Content]
) -> None: ) -> None:
"""Apply tool_call_extra metadata to the corresponding function call message. """Apply tool_call_extra metadata to the corresponding function call message.

View File

@@ -654,28 +654,6 @@ class LLMThoughtEndFrame(ControlFrame):
return f"{self.name}(pts: {pts}, signature: {self.signature})" return f"{self.name}(pts: {pts}, signature: {self.signature})"
@dataclass
class LLMThoughtSignatureFrame(DataFrame):
"""Frame containing a standalone LLM thought signature (as opposed to a thought signature associated with a thought).
This is useful for Gemini 3 Pro, which can output a signature at the end of
a response.
Parameters:
llm: Identifier of the LLM provider for LLM-specific handling.
Needed because the thought signature is appended to context as an
`LLMSpecificMessage`.
signature: The thought signature data.
"""
llm: str
signature: Any
def __str__(self):
pts = format_pts(self.pts)
return f"{self.name}(pts: {pts}, signature: {self.signature})"
@dataclass @dataclass
class LLMMessagesFrame(DataFrame): class LLMMessagesFrame(DataFrame):
"""Frame containing LLM messages for chat completion. """Frame containing LLM messages for chat completion.

View File

@@ -48,7 +48,6 @@ from pipecat.frames.frames import (
LLMSetToolChoiceFrame, LLMSetToolChoiceFrame,
LLMSetToolsFrame, LLMSetToolsFrame,
LLMThoughtEndFrame, LLMThoughtEndFrame,
LLMThoughtSignatureFrame,
LLMThoughtStartFrame, LLMThoughtStartFrame,
LLMThoughtTextFrame, LLMThoughtTextFrame,
SpeechControlParamsFrame, SpeechControlParamsFrame,
@@ -644,8 +643,6 @@ class LLMAssistantAggregator(LLMContextAggregator):
await self._handle_thought_text(frame) await self._handle_thought_text(frame)
elif isinstance(frame, LLMThoughtEndFrame): elif isinstance(frame, LLMThoughtEndFrame):
await self._handle_thought_end(frame) await self._handle_thought_end(frame)
elif isinstance(frame, LLMThoughtSignatureFrame):
await self._handle_standalone_thought_signature(frame)
elif isinstance(frame, LLMRunFrame): elif isinstance(frame, LLMRunFrame):
await self._handle_llm_run(frame) await self._handle_llm_run(frame)
elif isinstance(frame, LLMMessagesAppendFrame): elif isinstance(frame, LLMMessagesAppendFrame):
@@ -896,17 +893,6 @@ class LLMAssistantAggregator(LLMContextAggregator):
) )
) )
async def _handle_standalone_thought_signature(self, frame: LLMThoughtSignatureFrame):
self._context.add_message(
LLMSpecificMessage(
llm=frame.llm,
message={
"type": "thought_signature",
"signature": frame.signature,
},
)
)
def _context_updated_task_finished(self, task: asyncio.Task): def _context_updated_task_finished(self, task: asyncio.Task):
self._context_updated_tasks.discard(task) self._context_updated_tasks.discard(task)

View File

@@ -32,10 +32,10 @@ from pipecat.frames.frames import (
LLMContextFrame, LLMContextFrame,
LLMFullResponseEndFrame, LLMFullResponseEndFrame,
LLMFullResponseStartFrame, LLMFullResponseStartFrame,
LLMMessagesAppendFrame,
LLMMessagesFrame, LLMMessagesFrame,
LLMTextFrame, LLMTextFrame,
LLMThoughtEndFrame, LLMThoughtEndFrame,
LLMThoughtSignatureFrame,
LLMThoughtStartFrame, LLMThoughtStartFrame,
LLMThoughtTextFrame, LLMThoughtTextFrame,
LLMUpdateSettingsFrame, LLMUpdateSettingsFrame,
@@ -986,13 +986,12 @@ class GoogleLLMService(LLMService):
function_name=function_call.name, function_name=function_call.name,
arguments=function_call.args or {}, arguments=function_call.args or {},
append_extra_context_messages=[ append_extra_context_messages=[
LLMSpecificMessage( self.get_llm_adapter().create_llm_specific_message(
llm=self.get_llm_adapter().id_for_llm_specific_messages, {
message={ "type": "fn_thought_signature",
"type": "fn_call_thought_signature",
"signature": part.thought_signature, "signature": part.thought_signature,
"tool_call_id": id, "tool_call_id": id,
}, }
) )
] ]
if part.thought_signature if part.thought_signature
@@ -1011,9 +1010,15 @@ class GoogleLLMService(LLMService):
# calls. It will come in the last part of a response. # calls. It will come in the last part of a response.
if part.thought_signature and not part.function_call: if part.thought_signature and not part.function_call:
await self.push_frame( await self.push_frame(
LLMThoughtSignatureFrame( LLMMessagesAppendFrame(
llm=self.get_llm_adapter().id_for_llm_specific_messages, [
signature=part.thought_signature, self.get_llm_adapter().create_llm_specific_message(
{
"type": "non_fn_thought_signature",
"signature": part.thought_signature,
}
)
]
) )
) )