Skip to content
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 57 additions & 15 deletions src/google/adk/models/lite_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,20 +448,11 @@ async def _content_to_message_param(
*,
provider: str = "",
) -> Union[Message, list[Message]]:
"""Converts a types.Content to a litellm Message or list of Messages.

Handles multipart function responses by returning a list of
ChatCompletionToolMessage objects if multiple function_response parts exist.

Args:
content: The content to convert.
provider: The LLM provider name (e.g., "openai", "azure").

Returns:
A litellm Message, a list of litellm Messages.
"""
"""Converts a types.Content to a litellm Message or list of Messages."""

tool_messages = []
other_parts = []

for part in content.parts:
if part.function_response:
response = part.function_response.response
Expand All @@ -477,11 +468,62 @@ async def _content_to_message_param(
content=response_content,
)
)
if tool_messages:
else:
other_parts.append(part)

if tool_messages and not other_parts:
return tool_messages if len(tool_messages) > 1 else tool_messages[0]

# Handle user or assistant messages
role = _to_litellm_role(content.role)
extra_message = None

if other_parts:
role = _to_litellm_role(content.role)

if role == "user":
user_parts = [part for part in other_parts if not part.thought]
message_content = await _get_content(user_parts, provider=provider) or None
if message_content:
extra_message = ChatCompletionUserMessage(role="user", content=message_content)

else:
tool_calls = []
content_parts: list[types.Part] = []
reasoning_parts: list[types.Part] = []

for part in other_parts:
if part.function_call:
tool_calls.append(
ChatCompletionAssistantToolCall(
type="function",
id=part.function_call.id,
function=Function(
name=part.function_call.name,
arguments=_safe_json_serialize(part.function_call.args),
),
)
)
elif part.thought:
reasoning_parts.append(part)
else:
content_parts.append(part)

message_content = await _get_content(content_parts, provider=provider) or None
reasoning_content = "\n".join([p.thought for p in reasoning_parts]) if reasoning_parts else None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There appears to be a bug in the construction of reasoning_content. It's currently using p.thought, which seems to be a boolean flag, instead of p.text, which holds the actual reasoning text. This will result in incorrect content for the thought field of the ChatCompletionAssistantMessage.

Suggested change
reasoning_content = "\n".join([p.thought for p in reasoning_parts]) if reasoning_parts else None
reasoning_content = "\n".join([p.text for p in reasoning_parts if p.text]) if reasoning_parts else None


# Create the assistant message
extra_message = ChatCompletionAssistantMessage(
role="assistant",
content=message_content,
tool_calls=tool_calls if tool_calls else None,
thought=reasoning_content,
)

final_messages = tool_messages + ([extra_message] if extra_message else [])

if not final_messages:
return []

return final_messages if len(final_messages) > 1 else final_messages[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

After this return statement, there is a block of unreachable code from line 551 to 608. This seems to be leftover code from the refactoring that should be removed to improve code clarity and maintainability.


if role == "user":
user_parts = [part for part in content.parts if not part.thought]
Expand Down