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.

This commit is contained in:
Paul Kompfner
2025-08-21 16:56:32 -04:00
parent 04a50df3d5
commit a0a2bb3aa4

View File

@@ -161,7 +161,9 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
continue continue
# Convert standard format to Google format # 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): if isinstance(converted, Content):
# Regular (non-system) message # Regular (non-system) message
messages.append(converted) messages.append(converted)
@@ -187,7 +189,9 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
return self.ConvertedMessages(messages=messages, system_instruction=system_instruction) 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. """Convert universal context message to Google Content object.
Handles conversion of text, images, and function calls to Google's Handles conversion of text, images, and function calls to Google's
@@ -196,6 +200,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
Args: Args:
message: Message in universal context format. message: Message in universal context format.
already_have_system_instruction: Whether we already have a system instruction
Returns: Returns:
Content object with role and parts, or a plain string for system Content object with role and parts, or a plain string for system
@@ -240,6 +245,9 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
role = message["role"] role = message["role"]
content = message.get("content", []) content = message.get("content", [])
if role == "system": if role == "system":
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 # System instructions are returned as plain text
if isinstance(content, str): if isinstance(content, str):
return content return content