diff --git a/src/pipecat/adapters/services/gemini_adapter.py b/src/pipecat/adapters/services/gemini_adapter.py index 52d8cd114..f02f2acfc 100644 --- a/src/pipecat/adapters/services/gemini_adapter.py +++ b/src/pipecat/adapters/services/gemini_adapter.py @@ -222,10 +222,10 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): # messages if ( 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")) ): - self._apply_function_call_thought_signature_to_messages( + self._apply_function_thought_signature_to_messages( thought_signature, message.message.get("tool_call_id"), messages ) continue @@ -234,7 +234,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): # signature messages (Gemini 3 Pro) if ( 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")) ): 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, ) - 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] ) -> None: """Apply tool_call_extra metadata to the corresponding function call message. diff --git a/src/pipecat/frames/frames.py b/src/pipecat/frames/frames.py index 43cc357a2..335b92753 100644 --- a/src/pipecat/frames/frames.py +++ b/src/pipecat/frames/frames.py @@ -654,28 +654,6 @@ class LLMThoughtEndFrame(ControlFrame): 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 class LLMMessagesFrame(DataFrame): """Frame containing LLM messages for chat completion. diff --git a/src/pipecat/processors/aggregators/llm_response_universal.py b/src/pipecat/processors/aggregators/llm_response_universal.py index 2f7b5b97e..debfefb07 100644 --- a/src/pipecat/processors/aggregators/llm_response_universal.py +++ b/src/pipecat/processors/aggregators/llm_response_universal.py @@ -48,7 +48,6 @@ from pipecat.frames.frames import ( LLMSetToolChoiceFrame, LLMSetToolsFrame, LLMThoughtEndFrame, - LLMThoughtSignatureFrame, LLMThoughtStartFrame, LLMThoughtTextFrame, SpeechControlParamsFrame, @@ -644,8 +643,6 @@ class LLMAssistantAggregator(LLMContextAggregator): await self._handle_thought_text(frame) elif isinstance(frame, LLMThoughtEndFrame): await self._handle_thought_end(frame) - elif isinstance(frame, LLMThoughtSignatureFrame): - await self._handle_standalone_thought_signature(frame) elif isinstance(frame, LLMRunFrame): await self._handle_llm_run(frame) 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): self._context_updated_tasks.discard(task) diff --git a/src/pipecat/services/google/llm.py b/src/pipecat/services/google/llm.py index 393f2c814..0d1d18735 100644 --- a/src/pipecat/services/google/llm.py +++ b/src/pipecat/services/google/llm.py @@ -32,10 +32,10 @@ from pipecat.frames.frames import ( LLMContextFrame, LLMFullResponseEndFrame, LLMFullResponseStartFrame, + LLMMessagesAppendFrame, LLMMessagesFrame, LLMTextFrame, LLMThoughtEndFrame, - LLMThoughtSignatureFrame, LLMThoughtStartFrame, LLMThoughtTextFrame, LLMUpdateSettingsFrame, @@ -986,13 +986,12 @@ class GoogleLLMService(LLMService): function_name=function_call.name, arguments=function_call.args or {}, append_extra_context_messages=[ - LLMSpecificMessage( - llm=self.get_llm_adapter().id_for_llm_specific_messages, - message={ - "type": "fn_call_thought_signature", + self.get_llm_adapter().create_llm_specific_message( + { + "type": "fn_thought_signature", "signature": part.thought_signature, "tool_call_id": id, - }, + } ) ] if part.thought_signature @@ -1011,9 +1010,15 @@ class GoogleLLMService(LLMService): # calls. It will come in the last part of a response. if part.thought_signature and not part.function_call: await self.push_frame( - LLMThoughtSignatureFrame( - llm=self.get_llm_adapter().id_for_llm_specific_messages, - signature=part.thought_signature, + LLMMessagesAppendFrame( + [ + self.get_llm_adapter().create_llm_specific_message( + { + "type": "non_fn_thought_signature", + "signature": part.thought_signature, + } + ) + ] ) )