From a0a2bb3aa4767993ea6f1f03ee7a6c6bba38a1d9 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Thu, 21 Aug 2025 16:56:32 -0400 Subject: [PATCH] In `GeminiLLMAdapter`, when translating from the universal `LLMContext` format, only pull out the first "system" message as the system instruction, and convert subsequent ones into "user" messages. This is a more correct thing to do than simply drop subsequent "system" messages, especially when potentially sharing a context between multiple LLMs. --- .../adapters/services/gemini_adapter.py | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/pipecat/adapters/services/gemini_adapter.py b/src/pipecat/adapters/services/gemini_adapter.py index 732d008d6..31345821f 100644 --- a/src/pipecat/adapters/services/gemini_adapter.py +++ b/src/pipecat/adapters/services/gemini_adapter.py @@ -161,7 +161,9 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): continue # Convert standard format to Google format - converted = self._from_standard_message(message) + converted = self._from_standard_message( + message, already_have_system_instruction=bool(system_instruction) + ) if isinstance(converted, Content): # Regular (non-system) message messages.append(converted) @@ -187,7 +189,9 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): return self.ConvertedMessages(messages=messages, system_instruction=system_instruction) - def _from_standard_message(self, message: LLMStandardMessage) -> Content | str: + def _from_standard_message( + self, message: LLMStandardMessage, already_have_system_instruction: bool + ) -> Content | str: """Convert universal context message to Google Content object. Handles conversion of text, images, and function calls to Google's @@ -196,6 +200,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): Args: message: Message in universal context format. + already_have_system_instruction: Whether we already have a system instruction Returns: Content object with role and parts, or a plain string for system @@ -240,12 +245,15 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]): role = message["role"] content = message.get("content", []) if role == "system": - # System instructions are returned as plain text - if isinstance(content, str): - return content - elif isinstance(content, list): - # If content is a list, we assume it's a list of text parts, per the standard - return " ".join(part["text"] for part in content if part.get("type") == "text") + if already_have_system_instruction: + role = "user" # Convert system message to user role if we already have a system instruction + else: + # System instructions are returned as plain text + if isinstance(content, str): + return content + elif isinstance(content, list): + # If content is a list, we assume it's a list of text parts, per the standard + return " ".join(part["text"] for part in content if part.get("type") == "text") elif role == "assistant": role = "model"